- Day 17:pathlibで「ファイルとフォルダ」を安全に扱う
- pathlibの基本:Pathオブジェクトを理解する
- フォルダ操作:作成・存在確認・削除の基本
- ファイル作成:touch() と書き込みの入り口
- ファイル一覧:iterdir() と glob() の使い分け
- ファイル検索:条件付きで探す
- パス操作:親・名前・拡張子・絶対パス
- Day 17ミニテンプレート:pathlibファイルユーティリティ
- Day 17のまとめ
- Day 17:pathlibで「フォルダ分析ツール」を作る
- フォルダ分析ツールの全体像をイメージする
- pathlibの基本をフォルダ分析の文脈で押さえる
- ファイル一覧とフォルダ一覧を表示する
- 再帰的なファイル検索:rglob() を使いこなす
- フォルダ配下のファイル数・フォルダ数を集計する
- パス操作:親・名前・拡張子・絶対パスを理解する
- ファイル作成:分析結果をレポートとして保存する
- フォルダ分析ツールの全体テンプレート
- Day 17(制作編)のまとめ
Day 17:pathlibで「ファイルとフォルダ」を安全に扱う
Day 17では、Pythonの標準ライブラリ pathlib を使って、 ファイル検索・フォルダ操作・パス操作・ファイル作成・ファイル一覧を、初心者の方にも分かりやすい形で学んでいきます。 「文字列でパスをゴリゴリつなぐ世界」から、「パスをオブジェクトとして安全に扱う世界」へ一歩進むイメージです。
pathlibの基本:Pathオブジェクトを理解する
Path.cwd() と Path() の違い
pathlib の中心にあるのが Path クラスです。 これは「ファイルやフォルダへのパス」を表すオブジェクトで、文字列よりも安全で便利に扱えます。
from pathlib import Path
# 現在の作業ディレクトリ(カレントディレクトリ)を取得します
current = Path.cwd()
print("現在のディレクトリ:", current)
# 任意のパス文字列からPathオブジェクトを作成します
home = Path.home() # ユーザーのホームディレクトリ
print("ホームディレクトリ:", home)
some_path = Path("documents/report.txt")
print("任意のパス:", some_path)
PythonPath.cwd()は「今いるフォルダ」を表すPathを返します。Path.home()は「ユーザーのホームディレクトリ」を返します。Path("...")で任意のパス文字列からPathを作れます。
/ 演算子でパスを結合する
文字列で "/" を手動でつなぐ代わりに、Path では / 演算子を使ってパスを結合できます。
from pathlib import Path
base = Path.cwd()
logs_dir = base / "logs" # フォルダ
log_file = logs_dir / "app.log" # ファイル
print("ログフォルダ:", logs_dir)
print("ログファイル:", log_file)
Python- OSごとの区切り文字(
/や\)を意識する必要がなくなります。 - 「フォルダ/ファイル」という構造がコード上でも自然に見えるようになります。
フォルダ操作:作成・存在確認・削除の基本
フォルダの存在確認と作成
from pathlib import Path
logs_dir = Path("logs")
if logs_dir.exists():
print("logs フォルダはすでに存在しています。")
else:
logs_dir.mkdir() # フォルダを1つ作成します
print("logs フォルダを作成しました。")
PythonPath.exists()で「そのパスが存在するか」を確認できます。Path.mkdir()で「フォルダ」を作成できます。
親ディレクトリごと作成する(parents=True)
from pathlib import Path
nested_dir = Path("data/backup/2026")
# 親フォルダもまとめて作成したい場合
nested_dir.mkdir(parents=True, exist_ok=True)
print("ネストされたフォルダを作成しました:", nested_dir)
Pythonparents=Trueで「途中のフォルダもまとめて作成」できます。exist_ok=Trueで「すでに存在していてもエラーにしない」ようにできます。
ファイル作成:touch() と書き込みの入り口
空のファイルを作る(touch)
from pathlib import Path
log_file = Path("logs/app.log")
# 親フォルダがなければ作成しておきます
log_file.parent.mkdir(parents=True, exist_ok=True)
if not log_file.exists():
log_file.touch() # 空のファイルを作成します
print("ログファイルを作成しました:", log_file)
else:
print("ログファイルはすでに存在しています:", log_file)
PythonPath.touch()は「空のファイルを作る」メソッドです。path.parentで「そのファイルが属するフォルダ」を取得できます。
open() と組み合わせて書き込み
Path は open() メソッドも持っているので、ファイル操作と相性が良いです。
from pathlib import Path
log_file = Path("logs/app.log")
log_file.parent.mkdir(parents=True, exist_ok=True)
# 追記モードでログを書き込みます
with log_file.open("a", encoding="utf-8") as f:
f.write("アプリを起動しました。\n")
print("ログを書き込みました。")
Pythonlog_file.open("a", ...)はopen(str(log_file), "a", ...)と同じ意味ですが、Pathと一貫性が保てます。
ファイル一覧:iterdir() と glob() の使い分け
iterdir() で「直下の中身」を列挙する
from pathlib import Path
target = Path.cwd()
print("現在のディレクトリの中身:")
for entry in target.iterdir():
if entry.is_dir():
kind = "フォルダ"
elif entry.is_file():
kind = "ファイル"
else:
kind = "その他"
print(f"{kind}: {entry.name}")
PythonPath.iterdir()は「そのフォルダ直下のエントリ」を返します。is_dir()・is_file()で「フォルダかファイルか」を判定できます。
glob() で「パターンに合うファイル」を検索する
from pathlib import Path
target = Path.cwd()
print("このフォルダ内の .py ファイル一覧:")
for py_file in target.glob("*.py"):
print(" -", py_file.name)
Pythonglob("パターン")は「ワイルドカード付きの検索」を行います。"*.py"は「拡張子が.pyのファイル」を意味します。
rglob() で「サブフォルダも含めて検索する」
from pathlib import Path
target = Path.cwd()
print("このフォルダ以下すべての .txt ファイル一覧:")
for txt_file in target.rglob("*.txt"):
print(" -", txt_file)
Pythonrglob()は「再帰的な glob」であり、サブフォルダも含めて検索します。
ファイル検索:条件付きで探す
特定サイズ以上のファイルを探す
from pathlib import Path
target = Path.cwd()
threshold = 1024 * 100 # 100KB以上
print(f"{target} 以下で、サイズが100KB以上のファイルを探します。")
for file in target.rglob("*"):
if file.is_file():
size = file.stat().st_size
if size >= threshold:
print(f"{file} ({size} bytes)")
Pythonfile.stat().st_sizeで「ファイルサイズ(バイト)」を取得できます。- 条件付きでフィルタすることで、「重いファイルだけ」「古いファイルだけ」などの検索ができます。
更新日時で絞り込む
from pathlib import Path
from datetime import datetime, timedelta
target = Path.cwd()
days = 7 # 7日以内に更新されたファイル
limit = datetime.now() - timedelta(days=days)
print(f"{target} 以下で、直近 {days} 日以内に更新されたファイルを探します。")
for file in target.rglob("*"):
if file.is_file():
mtime = datetime.fromtimestamp(file.stat().st_mtime)
if mtime >= limit:
print(f"{file} (更新日時: {mtime})")
Pythondatetime.fromtimestamp()で「UNIXタイム → datetime」に変換できます。timedelta(days=...)と比較することで、「最近更新されたファイル」を探せます。
パス操作:親・名前・拡張子・絶対パス
親ディレクトリ・ファイル名・拡張子
from pathlib import Path
p = Path("logs/app.log")
print("フルパス:", p)
print("親ディレクトリ:", p.parent)
print("ファイル名:", p.name)
print("拡張子:", p.suffix)
print("拡張子なしの名前:", p.stem)
Pythonparent→ 親ディレクトリname→ ファイル名(拡張子込み)suffix→ 拡張子(例:.log)stem→ 拡張子を除いた名前
絶対パスに変換する
from pathlib import Path
p = Path("logs/app.log")
abs_path = p.resolve()
print("相対パス:", p)
print("絶対パス:", abs_path)
Pythonresolve()は「実際の絶対パス」を返します(シンボリックリンクなども解決します)。
Day 17ミニテンプレート:pathlibファイルユーティリティ
最後に、Day 17で学んだ内容をまとめた「簡易ファイルユーティリティ」のテンプレートを示します。
# day17_pathlib_tool.py
# pathlibを使ったファイル・フォルダ操作の練習ツール
from pathlib import Path
from datetime import datetime, timedelta
def choose_directory():
text = input("対象フォルダのパスを入力してください(空ならカレントディレクトリ): ").strip()
if text == "":
directory = Path.cwd()
else:
directory = Path(text)
if not directory.exists():
print("指定されたフォルダは存在しません。")
return None
if not directory.is_dir():
print("指定されたパスはフォルダではありません。")
return None
return directory
def list_files(directory: Path):
print(f"\n=== {directory} の直下のファイル一覧 ===")
for entry in directory.iterdir():
if entry.is_file():
print("ファイル:", entry.name)
elif entry.is_dir():
print("フォルダ:", entry.name)
def search_py_files_recursive(directory: Path):
print(f"\n=== {directory} 以下の .py ファイル一覧 ===")
for py_file in directory.rglob("*.py"):
print(py_file)
def search_recent_files(directory: Path, days: int = 7):
limit = datetime.now() - timedelta(days=days)
print(f"\n=== 直近 {days} 日以内に更新されたファイル ===")
for file in directory.rglob("*"):
if file.is_file():
mtime = datetime.fromtimestamp(file.stat().st_mtime)
if mtime >= limit:
print(f"{file} (更新日時: {mtime})")
def create_log_file(directory: Path):
logs_dir = directory / "logs"
logs_dir.mkdir(parents=True, exist_ok=True)
log_file = logs_dir / "app.log"
if not log_file.exists():
log_file.touch()
print("ログファイルを作成しました:", log_file)
else:
print("ログファイルはすでに存在しています:", log_file)
def main():
directory = choose_directory()
if directory is None:
return
while True:
print("\n=== pathlib ファイルユーティリティ ===")
print(f"対象フォルダ: {directory}")
print("1: 直下のファイル・フォルダ一覧を表示する")
print("2: .py ファイルを再帰的に検索する")
print("3: 直近7日以内に更新されたファイルを検索する")
print("4: logs/app.log を作成する")
print("5: 終了する")
choice = input("番号を入力してください: ").strip()
if choice == "1":
list_files(directory)
elif choice == "2":
search_py_files_recursive(directory)
elif choice == "3":
search_recent_files(directory, days=7)
elif choice == "4":
create_log_file(directory)
elif choice == "5":
print("pathlib ファイルユーティリティを終了します。")
break
else:
print("1〜5の番号を入力してください。")
if __name__ == "__main__":
main()
PythonDay 17のまとめ
Day 17では、pathlib を通して、
- パスを「文字列」ではなく「オブジェクト」として扱う感覚
- フォルダ作成・存在確認・親ディレクトリ取得などの基本操作
iterdir()・glob()・rglob()によるファイル一覧・ファイル検索touch()・open()によるファイル作成と書き込みの入り口- 親・名前・拡張子・絶対パスといったパス操作の基本
をステップバイステップで体験していただきました。
ここまで来ると、「ファイルとフォルダを扱うコードが、ぐっと読みやすく・安全になる」という感覚が少し育っているはずです。 この感覚は、今後の実践Python編でログ管理・バックアップ・自動化スクリプトなどを作っていくうえで、強力な土台になっていきます。
Day 17:pathlibで「フォルダ分析ツール」を作る
Day 17の制作編では、pathlib を中心に、 ファイル検索・フォルダ操作・パス操作・ファイル作成・ファイル一覧を組み合わせた「フォルダ分析ツール」を作っていきます。 フォルダの中身をざっくり把握したり、特定のファイルだけを抽出したりできる、実用的なCLIツールを目指します。
フォルダ分析ツールの全体像をイメージする
どんなことができるツールか
今回のフォルダ分析ツールでは、次のような機能を持たせます。
- 対象フォルダを指定する
- 直下のファイル・フォルダ一覧を表示する
- 再帰的にファイルを検索する(例:
*.pyや*.txt) - フォルダ配下のファイル数・フォルダ数を集計する
- 分析結果をテキストファイルとして保存する(ファイル作成)
この流れの中で、
- ファイル検索 →
rglob() - フォルダ操作 →
mkdir()・exists()・is_dir() - パス操作 →
parent・name・suffix・resolve() - ファイル作成 →
touch()・open() - ファイル一覧 →
iterdir()
を自然に使っていきます。
pathlibの基本をフォルダ分析の文脈で押さえる
対象フォルダを選ぶ関数
まずは、ユーザーに「分析したいフォルダ」を入力してもらい、Path オブジェクトとして扱えるようにします。
from pathlib import Path
def choose_directory():
"""対象フォルダをユーザーに入力してもらい、Pathとして返す関数です。"""
text = input("分析したいフォルダのパスを入力してください(空ならカレントディレクトリ): ").strip()
if text == "":
directory = Path.cwd() # 現在のディレクトリ
else:
directory = Path(text) # 入力された文字列からPathを作成
if not directory.exists():
print("指定されたフォルダは存在しません。")
return None
if not directory.is_dir():
print("指定されたパスはフォルダではありません。")
return None
return directory
Pythonここでの重要ポイントは、
Path.cwd()で「今いるフォルダ」を簡単に取得できることPath(text)で「文字列 → パスオブジェクト」に変換できることexists()とis_dir()で「存在するか」「フォルダかどうか」をチェックできること
です。これにより、「存在しないパス」や「ファイルをフォルダとして扱ってしまう」ミスを防ぎやすくなります。
ファイル一覧とフォルダ一覧を表示する
iterdir() で直下の中身を列挙する
フォルダ分析の基本は、「中に何があるか」を一覧することです。 iterdir() を使って、直下のファイル・フォルダを表示する関数を作ります。
from pathlib import Path
def show_direct_children(directory: Path):
"""対象フォルダ直下のファイル・フォルダ一覧を表示する関数です。"""
print(f"\n=== {directory} の直下の一覧 ===")
has_entries = False
for entry in directory.iterdir():
has_entries = True
if entry.is_dir():
kind = "フォルダ"
elif entry.is_file():
kind = "ファイル"
else:
kind = "その他"
print(f"{kind}: {entry.name}")
if not has_entries:
print("このフォルダには何もありません。")
Pythonここでは、
iterdir()で「直下のエントリ」を1つずつ取り出しています。is_dir()・is_file()で種類を判定し、ユーザーに分かりやすく表示しています。
フォルダ分析ツールの「最初の一歩」として、とても重要な機能です。
再帰的なファイル検索:rglob() を使いこなす
特定の拡張子のファイルをフォルダ以下すべてから探す
フォルダ分析では、「このフォルダ以下の .py ファイルを全部見たい」「.txt だけ抽出したい」といったニーズがよくあります。 rglob() を使うと、サブフォルダも含めて検索できます。
from pathlib import Path
def search_files_by_pattern(directory: Path, pattern: str):
"""指定したパターンに合うファイルを再帰的に検索して表示する関数です。"""
print(f"\n=== {directory} 以下の {pattern} に合うファイル一覧 ===")
found = False
for file in directory.rglob(pattern):
if file.is_file():
found = True
print(file)
if not found:
print("該当するファイルは見つかりませんでした。")
Python使い方の例:
# .pyファイルを探す
search_files_by_pattern(directory, "*.py")
# .txtファイルを探す
search_files_by_pattern(directory, "*.txt")
Pythonここでの重要ポイントは、
rglob("*.py")で「サブフォルダも含めて.pyファイルを検索」できること- パターンを引数にしておくことで、汎用的な検索関数になること
です。
フォルダ配下のファイル数・フォルダ数を集計する
再帰的に数を数える
フォルダ分析ツールらしく、「このフォルダ以下にファイルが何個、フォルダが何個あるか」を集計する関数を作ります。
from pathlib import Path
def count_entries_recursive(directory: Path):
"""フォルダ以下のファイル数・フォルダ数を再帰的に集計する関数です。"""
file_count = 0
dir_count = 0
for entry in directory.rglob("*"):
if entry.is_file():
file_count += 1
elif entry.is_dir():
dir_count += 1
print(f"\n=== {directory} 以下の集計結果 ===")
print(f"ファイル数: {file_count}")
print(f"フォルダ数: {dir_count}")
Pythonここでは、
rglob("*")で「すべてのエントリ」を対象にしています。is_file()とis_dir()で種類を判定し、カウンタを増やしています。
これにより、「このプロジェクトはどれくらいの規模か」をざっくり把握できるようになります。
パス操作:親・名前・拡張子・絶対パスを理解する
パスの分解を分析に活かす
フォルダ分析では、「どのフォルダにどんな拡張子のファイルがあるか」を知りたいこともあります。 parent・name・suffix・stem を使うと、パスを柔軟に扱えます。
from pathlib import Path
def show_path_details(path: Path):
"""1つのパスについて、親・名前・拡張子などを表示する関数です。"""
print("\n=== パスの詳細情報 ===")
print("フルパス:", path)
print("絶対パス:", path.resolve())
print("親ディレクトリ:", path.parent)
print("ファイル名:", path.name)
print("拡張子:", path.suffix)
print("拡張子なしの名前:", path.stem)
Pythonこの関数は、分析ツールの中で「特定のファイルを詳しく見たい」ときに使えます。
ファイル作成:分析結果をレポートとして保存する
reports フォルダにテキストレポートを作る
フォルダ分析ツールを「実用的なツール」に近づけるために、分析結果をテキストファイルとして保存する機能を追加します。
from pathlib import Path
from datetime import datetime
def save_report(directory: Path, file_count: int, dir_count: int):
"""分析結果を reports フォルダにテキストレポートとして保存する関数です。"""
reports_dir = directory / "reports"
reports_dir.mkdir(parents=True, exist_ok=True) # 親ごと作成
# 日付入りのファイル名を作成します
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
report_file = reports_dir / f"report_{timestamp}.txt"
# ファイルを作成して書き込みます
with report_file.open("w", encoding="utf-8") as f:
f.write(f"フォルダ分析レポート\n")
f.write(f"対象フォルダ: {directory}\n")
f.write(f"作成日時: {datetime.now()}\n")
f.write("\n")
f.write(f"ファイル数: {file_count}\n")
f.write(f"フォルダ数: {dir_count}\n")
print("分析レポートを保存しました:", report_file)
Pythonここでの重要ポイントは、
directory / "reports"で「対象フォルダ配下に reports フォルダ」を作ることmkdir(parents=True, exist_ok=True)で「安全にフォルダを作成」していることopen("w", ...)で「テキストファイルを作成し、分析結果を書き込んでいる」こと
です。これにより、「分析結果を後から見返せる」ツールになります。
フォルダ分析ツールの全体テンプレート
ここまでの関数を組み合わせて、「フォルダ分析ツール」として動く全体コードをまとめます。
# day17_folder_analyzer.py
# pathlibを使ったフォルダ分析ツール
from pathlib import Path
from datetime import datetime
def choose_directory():
text = input("分析したいフォルダのパスを入力してください(空ならカレントディレクトリ): ").strip()
if text == "":
directory = Path.cwd()
else:
directory = Path(text)
if not directory.exists():
print("指定されたフォルダは存在しません。")
return None
if not directory.is_dir():
print("指定されたパスはフォルダではありません。")
return None
return directory
def show_direct_children(directory: Path):
print(f"\n=== {directory} の直下の一覧 ===")
has_entries = False
for entry in directory.iterdir():
has_entries = True
if entry.is_dir():
kind = "フォルダ"
elif entry.is_file():
kind = "ファイル"
else:
kind = "その他"
print(f"{kind}: {entry.name}")
if not has_entries:
print("このフォルダには何もありません。")
def search_files_by_pattern(directory: Path, pattern: str):
print(f"\n=== {directory} 以下の {pattern} に合うファイル一覧 ===")
found = False
for file in directory.rglob(pattern):
if file.is_file():
found = True
print(file)
if not found:
print("該当するファイルは見つかりませんでした。")
def count_entries_recursive(directory: Path):
file_count = 0
dir_count = 0
for entry in directory.rglob("*"):
if entry.is_file():
file_count += 1
elif entry.is_dir():
dir_count += 1
print(f"\n=== {directory} 以下の集計結果 ===")
print(f"ファイル数: {file_count}")
print(f"フォルダ数: {dir_count}")
return file_count, dir_count
def save_report(directory: Path, file_count: int, dir_count: int):
reports_dir = directory / "reports"
reports_dir.mkdir(parents=True, exist_ok=True)
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
report_file = reports_dir / f"report_{timestamp}.txt"
with report_file.open("w", encoding="utf-8") as f:
f.write("フォルダ分析レポート\n")
f.write(f"対象フォルダ: {directory}\n")
f.write(f"作成日時: {datetime.now()}\n")
f.write("\n")
f.write(f"ファイル数: {file_count}\n")
f.write(f"フォルダ数: {dir_count}\n")
print("分析レポートを保存しました:", report_file)
def main():
directory = choose_directory()
if directory is None:
return
while True:
print("\n=== フォルダ分析ツール(pathlib版) ===")
print(f"対象フォルダ: {directory}")
print("1: 直下のファイル・フォルダ一覧を表示する")
print("2: パターンでファイル検索する(例: *.py)")
print("3: フォルダ以下のファイル数・フォルダ数を集計する")
print("4: 集計結果をレポートとして保存する")
print("5: 終了する")
choice = input("番号を入力してください: ").strip()
if choice == "1":
show_direct_children(directory)
elif choice == "2":
pattern = input("検索パターンを入力してください(例: *.py, *.txt): ").strip()
if pattern:
search_files_by_pattern(directory, pattern)
else:
print("パターンが空です。")
elif choice == "3":
file_count, dir_count = count_entries_recursive(directory)
elif choice == "4":
file_count, dir_count = count_entries_recursive(directory)
save_report(directory, file_count, dir_count)
elif choice == "5":
print("フォルダ分析ツールを終了します。")
break
else:
print("1〜5の番号を入力してください。")
if __name__ == "__main__":
main()
PythonDay 17(制作編)のまとめ
Day 17の制作編では、「フォルダ分析ツール」を通して、
Pathを使った安全で読みやすいパス操作iterdir()・rglob()によるファイル一覧・ファイル検索exists()・is_dir()によるフォルダの存在確認とエラー防止mkdir()・open()によるフォルダ作成・レポートファイル作成- フォルダ配下のファイル数・フォルダ数の集計と、その結果の保存
を一つのプログラムの中で体験していただきました。
ここまで来ると、「pathlibを使うと、ファイルとフォルダを扱うコードがぐっと整理される」という感覚が少し育っているはずです。 この感覚は、今後の実践Python編でログ管理・バックアップ・自動分析ツールなどを作っていくうえで、強力な土台になっていきます。
