【Python入門】指定ディレクトリのファイル一覧を取得する方法|os・glob・pathlibの使い分け

Python

作業をしているとサブディレクトリを含む全てのファイル名を取得したい場合があると思います。

Pythonで特定のフォルダ(ディレクトリ)内にあるファイル名を一覧で取得したいときは、osモジュールやglobモジュール、pathlibなどを使うのが一般的です。本記事では、初心者の方でもわかりやすいように、それぞれの方法の使い方・違い・注意点を具体例付きで解説します。

この記事の対象

  • glob、osの使用方法を知りたい方
  • ファイル名を簡単に取得したい方
  • ルートディレクトリでファイルを取得したい方
スポンサーリンク
スポンサーリンク

ファイル一覧を取得する主な3つの方法

方法特徴Pythonバージョン
os.listdir()標準的で古くからあるすべて対応
glob.glob()ワイルドカードで柔軟な検索が可能すべて対応
pathlibオブジェクト指向で書きやすい3.4以降推奨

os.listdir() を使った基本例

import os

files = os.listdir('sample_dir')
print(files)  # ファイル名とフォルダ名がリストで返る

ディレクトリ内の「ファイル」だけでなく「サブフォルダ」も含まれる点に注意。

glob.glob() を使った方法

import glob

files = glob.glob('sample_dir/*')  # フルパスで取得
print(files)

*.txt と指定すれば、特定の拡張子だけ取得できます。

pathlib を使う(Pythonicな書き方)

from pathlib import Path

p = Path('sample_dir')
files = [f.name for f in p.iterdir() if f.is_file()]
print(files)

拡張性が高く、オブジェクト指向で記述がきれいになります。

ファイルだけを抽出する(isfileの利用)

import os

files = [f for f in os.listdir('sample_dir') if os.path.isfile(os.path.join('sample_dir', f))]
print(files)

os.path.isfile() を使うことでサブディレクトリを除外できます。

具体的な使用例

ファルダ内にあるexcelファル名を取得して出力しました。

globを用いた場合

カレントディレクトリのみ

import glob
#1---フォルダ内のxlsxファイルの一覧を取得
files = sorted(glob.glob('*.csv'))
print(files)

ファイルの一覧を取得するには「glob()」関数を用いることが簡単です。

「glob.glob(‘*.csv’)」として、フォルダ内の全てのcsvファイルを指定しています。「sorted()」関数では出力時、見やすいように並び替えをしています。

最後に出力です。

結果
['7731_2010.csv', '7731_2011.csv', '7731_2012.csv', '7731_2013.csv', '7731_2014.csv', '7731_2015.csv', '7731_2016.csv', '7731_2017.csv', '7731_2018.csv', '7731_2019.csv', '7731_2020.csv']

サブディレクトリを含む

import glob
for f in glob.glob("./**/*.*", recursive=True):
    print(f)

サブディレクトリ内のファイル名を取得したい場合は、引数にpath(ワイルドカードを用いて)と「recursive」をTrueにする事で簡単に取得できます。

osを用いた場合

import os

#1---ファイルを検索するルートディレクトリのパス
root_dir = r'C:\hoge\hoge\src'

#2---ルートディレクトリ以下の全てのファイルを取得
for dirpath, dirnames, filenames in os.walk(root_dir):
    for filename in filenames:
        #3---ファイルパスを取得
        file_path = os.path.join(dirpath, filename)
        print(file_path)

上記のコードでは、os.walk()メソッドを使用して、指定されたルートディレクトリ以下の全てのファイルを再帰的に検索しています。

以下は解説になります。

#1---ファイルを検索するルートディレクトリのパス
root_dir = r'C:\hoge\hoge\src'

1の部分ではディレクトリを指定しています。

#2---ルートディレクトリ以下の全てのファイルを取得
for dirpath, dirnames, filenames in os.walk(root_dir):

2の部分ではos.walk()メソッドを用いてファイル名を取得しています。

#3---ファイルパスを取得
file_path = os.path.join(dirpath, filename)
print(file_path)

最後にファイルのpathを作成して出力しています。

まとめ:使い分けのポイント

状況推奨手法
とにかく一覧を取得したいos.listdir()
拡張子やパターンで絞りたいglob.glob()
直感的で拡張性の高いコードを書きたいpathlib

おまけ:ファイル名を取得して、csv出力

指定フォルダ配下を(任意で再帰的に)走査し、ファイル名やサイズ、更新日時、フルパスなどを CSV に出力します。Excel で開きやすい UTF-8 (BOM 付き) で保存するスクリプトです。

使い方

# 引用符なしでもOK(-r 以降はオプションとして認識されます)
python filelist_to_csv.py C:\Users\Public\Pictures\ Sample Photos -r -p "*.jpg"

# 出力先にもスペースOK(引用符なし)
python filelist_to_csv.py "D:\作業 フォルダ" -o D:\出力 フォルダ\一覧 出力.csv

スクリプト

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
日本語/スペースを含むパス対応版:ファイル一覧→CSV 出力
- folder と -o/--output は 複数トークンを結合して1つのパスとして解釈(引用符なしでもOK)
- 出力CSV: 既定 utf-8-sig(Excel 互換)
- パターン複数(;区切り)、再帰、隠しファイル(先頭ドット)含む/除外切替
"""
import argparse
import csv
import sys
from pathlib import Path
from datetime import datetime

def configure_stdout_utf8():
    try:
        if hasattr(sys.stdout, "reconfigure"):
            sys.stdout.reconfigure(encoding="utf-8")
        if hasattr(sys.stderr, "reconfigure"):
            sys.stderr.reconfigure(encoding="utf-8")
    except Exception:
        pass

def is_hidden_like(p: Path) -> bool:
    return p.name.startswith('.')

def ts_to_iso(ts: float) -> str:
    try:
        return datetime.fromtimestamp(ts).isoformat(timespec='seconds')
    except Exception:
        return ""

def iter_files(root: Path, patterns, recursive: bool, include_hidden: bool):
    if not patterns:
        patterns = ['*']
    seen = set()
    for pat in patterns:
        gen = root.rglob(pat) if recursive else root.glob(pat)
        for p in gen:
            if not p.is_file():
                continue
            if not include_hidden and is_hidden_like(p):
                continue
            try:
                key = p.resolve(strict=False)
            except Exception:
                key = p
            if key in seen:
                continue
            seen.add(key)
            yield p

def write_csv(rows, out_path: Path, encoding: str, delimiter: str):
    out_path.parent.mkdir(parents=True, exist_ok=True)
    with out_path.open('w', newline='', encoding=encoding, errors="replace") as f:
        w = csv.writer(f, delimiter=delimiter, quoting=csv.QUOTE_MINIMAL)
        w.writerow([
            "name", "stem", "suffix", "size",
            "mtime_iso", "atime_iso", "ctime_iso",
            "abs_path", "rel_path"
        ])
        for r in rows:
            w.writerow(r)

def main():
    configure_stdout_utf8()

    ap = argparse.ArgumentParser(description="フォルダ内のファイル一覧をCSVに出力(日本語・スペース対応)。")
    # ★ 複数トークンを結合して1パス化(引用符なし対策)
    ap.add_argument("folder", nargs="+", help="走査対象フォルダ(日本語/スペース可、複数語を結合)")
    ap.add_argument("-o", "--output", nargs="+", default=None,
                    help="出力CSVパス(スペース可。省略時: ./filelist_YYYYmmdd_HHMMSS.csv)")
    ap.add_argument("-p", "--pattern", default="*",
                    help="マッチパターン。例: *.png;*.jpg(; 区切りで複数)")
    ap.add_argument("-r", "--recursive", action="store_true", help="サブフォルダも再帰的に走査")
    ap.add_argument("--include-hidden", action="store_true", help="先頭ドットの隠しっぽいファイルも含める")
    ap.add_argument("-e", "--encoding", default="utf-8-sig",
                    help="CSV文字コード(既定: utf-8-sig。Excel厳しい環境は cp932)")
    ap.add_argument("--delimiter", default=",", help="CSV区切り文字(既定: ,)")
    args = ap.parse_args()

    root = Path(" ".join(args.folder)).expanduser()
    if not root.exists() or not root.is_dir():
        raise SystemExit(f"フォルダが見つかりません: {root}")

    patterns = [p.strip() for p in args.pattern.split(";") if p.strip()]

    if args.output:
        out_path = Path(" ".join(args.output)).expanduser()
    else:
        ts = datetime.now().strftime("%Y%m%d_%H%M%S")
        out_path = Path(f"./filelist_{ts}.csv")

    rows = []
    for p in iter_files(root, patterns, args.recursive, args.include_hidden):
        try:
            st = p.stat()
        except Exception:
            st = None
        size  = st.st_size if st else ""
        mtime = ts_to_iso(st.st_mtime) if st else ""
        atime = ts_to_iso(st.st_atime) if st else ""
        ctime = ts_to_iso(st.st_ctime) if st else ""
        try:
            abs_path = str(p.resolve(strict=False))
        except Exception:
            abs_path = str(p.absolute())
        try:
            rel_path = str(p.relative_to(root))
        except Exception:
            rel_path = p.name

        rows.append([p.name, p.stem, p.suffix, size,
                     mtime, atime, ctime, abs_path, rel_path])

    write_csv(rows, out_path, encoding=args.encoding, delimiter=args.delimiter)
    print(f"ファイル数: {len(rows)}")
    print(f"出力: {out_path}")

if __name__ == "__main__":
    main()

CMD/PowerShellの仕様上、通常はスペースを含むパスは引用符で囲む必要がありますが、このスクリプトは folder-o/–output に限り、引用符なしでも正しく結合して解釈します。

それ以外のオプション値にスペースを含めたい場合は、引き続き引用符で囲んでください。

関連記事

ファイル名を取得したら、次はファイルの読み書き方法も学んでみましょう!

タイトルとURLをコピーしました