ファイルを列挙する(再帰なし)
Python の os.listdir
関数を使うと、指定したディレクトリ内のファイルやディレクトリのパスをリストで取得できます。
カレントディレクトリや親ディレクトリを表す .
や ..
は、列挙の対象に含まれません。
列挙されたパスが、ディレクトリかどうかを調べたいときは os.path.isdir(path)
、ファイルかどうかを調べたいときは os.path.isfile(path)
で確認できます。
import os
for x in os.listdir('.'):
if os.path.isdir(x):
print('DIR:', x)
else:
print('FILE:', x)
ファイルを列挙する(再帰あり)
os.listdir で列挙する方法
os.listdir
関数で列挙した要素がディレクトリだった場合に、そのディレクトリに対しても os.listdir
関数を呼び出すようにすれば、ディレクトリ内のすべてのファイルを再帰的に列挙することができます。
import os
def enum_files(dir):
entries = os.listdir(dir)
for x in entries:
path = os.path.join(dir, x)
if os.path.isdir(path):
for _ in enum_files(path): yield _
else:
yield path
if __name__ == '__main__':
for path in enum_files('.'):
print(path)
# print(os.path.abspath(path)) # 絶対パスで出力する場合
os.walk で列挙する方法
os.walk 関数 を使用すると、再帰的なファイル列挙をさらに簡単に記述できます。
下記は 1 つのループ処理で記述していますが、下位のディレクトリにあるファイルまですべて列挙してくれます。
os.walk
はデフォルトで再帰的にディレクトリを辿ってくれる ということです。
import os
for dirpath, dirs, files in os.walk("."):
print("-" * 60)
print(f"{dirpath} ディレクトリの情報:")
print(f"dirs = {dirs}")
print(f"files = {files}")
os.walk
によって取得されるタプル要素には、それぞれ以下のような情報が格納されています。
dirpath
… 現在検索中のディレクトリパスdirs
…dirpath
のディレクトリに含まれているディレクトリのリストfiles
…dirpath
のディレクトリに含まれているファイルのリスト
つまり、ディレクトリごとに上記のタプルが返されながらループが進んでいきます。
カレントディレクトリ以下のすべてのファイルのパスだけを列挙するには次のように files
(タプルの 3 番目の要素)の内容だけ出力すれば OK です。
起点となるディレクトリのパス (dirpath
) と join
してやれば、そこからの相対パスを構築できます。
import os
for dirpath, dirs, files in os.walk('.'):
for f in files:
print(os.path.join(dirpath, f))
./a.txt
./b.txt
./foo/c.txt
./foo/d.txt
./foo/bar/e.txt
./foo/bar/f.txt
./hoge/g.txt
特定の拡張子のファイルだけ列挙したい場合 は、ファイル名の末尾を str.endswith
メソッドでチェックすればよいでしょう。
for f in files:
if f.lower().endswith('.png'):
print(os.path.join(dirpath, f))
endswith()
にはタプルを渡せるので、複数の拡張子を OR 条件で列挙することもできます。
for f in files:
if f.lower().endswith(('.png', '.jpg', '.svg')):
print(os.path.join(dirpath, f))
os.path.splitext() を使用すれば、ファイル名をベースネームと拡張子に分離することができますが、拡張子のチェックだけであれば、endswith()
を使った方がシンプルです。
glob で列挙する方法
ディレクトリ内の、特定の拡張子を持つファイルをすべて列挙したいときは、glob モジュール の glob.glob
関数を使うのが一番簡単です。
次のようにすると、カレントディレクト以下の .png
ファイルをすべて列挙できます。
import os
import glob
for x in glob.glob('**/*.png', recursive=True):
print(x)
ただし、グロブでは複数の拡張子をまとめて処理できない ので、複数の拡張子のファイルを列挙したい場合は、その数だけ glob.glob()
を呼び出さなければいけません。
import os
import glob
PATTERNS = ('**/*.png', '**/*.jpg')
def multi_glob(patterns):
files = []
for p in PATTERNS:
files.extend(glob.glob(p, recursive=True))
return files
for f in multi_glob(PATTERNS):
print(f)
このような実装をするのであれば、os.walk を使って列挙した方が早いかもしれません。