ファイルを色々操作するために、ファイルの一覧を取得したい、
というときはglob
を使うらしいのでメモ。
前提
下記のようなファイル構造であるとする。
. ─┬─ text01.txt ├─ text02.txt ├─ Excel01.xlsx ├─ Excel02.xlsx ├─ pdf01.pdf ├─ pdf02.pdf ├─ folder01 ───┬─ folder02 ─── text05.txt │ ├─ text03.txt │ └─ text04.txt └─ folder03 ───── text06.txt
以降 glob
を使うのでインポートしておく。
>>> import glob
一覧の取得
glob.glob( )
でファイル名を取得する。
>>> files = glob.glob('*') #全ファイル名を取得 >>> print(files) ['Excel01.xlsx', 'Excel02.xlsx', 'folder01', 'folder03', 'pdf01.pdf', 'pdf02.pdf', 'text01.txt', 'text02.txt']
確かにファイル名は取得できたが、フォルダも混ざっている。そしてサブフォルダ内のファイルは取得できていない。
そこで、*.txt
でテキストファイルだけ取得するようにしてみる。
>>> files = glob.glob('*.txt') #テキストファイルだけを取得 >>> print(files) ['text01.txt', 'text02.txt']
テキストファイルのみ取得できた。次にフォルダ内のテキストファイルを取得してみる。
>>> files = glob.glob('*/*.txt') #フォルダ内のファイルを取得。ただしその階層のみ >>> print(files) ['folder01\\text03.txt', 'folder01\\text04.txt', 'folder03\\text06.txt']
フォルダ内のテキストが取得できたが、*/*.txt
の構造(カレントディレクトリにあるフォルダ内(1階層のみ))のテキストファイルしか取得できていない。
このようなときは、**/*.txt
とrecursive=True
を指定することで、フォルダ階層を再帰的に探索してくれる。
>>> files = glob.glob('**/*.txt', recursive=True) #現在のフォルダを含むすべてのサブフォルダからフ ァイルを取得 >>> print(files) ['text01.txt', 'text02.txt', 'folder01\\text03.txt', 'folder01\\text04.txt', 'folder01\\folder02\\text05.txt', 'folder03\\text06.txt']
これでサブフォルダを含むすべてのフォルダからファイル名を取得することができた。
ファイル構造を含まないファイル名
上の結果では、取得したファイル名にパスを含んでいる。パスが不要な場合、パスを取り除く処理をする。
ここではsplit( )
、basename( )
を使うので、os
をインポートしておく。
>>> import os
split( )
でパスとファイル名を分けることができる。結果は長さ2のタプルで返ってくる。
>>> print(os.path.split(files[0])) ('', 'text01.txt') >>> print(os.path.split(files[2])) ('folder01', 'text03.txt') >>> print(os.path.split(files[4])) ('folder01\\folder02', 'text05.txt')
パスの情報が必要なければ、basename( )
でファイル名だけ取得することができる。
>>> print(os.path.basename(files[0])) #basenameはファイル名だけを出力する text01.txt >>> print(os.path.basename(files[2])) text03.txt >>> print(os.path.basename(files[4])) text05.txt
なおsplit( )
の結果はタプルなので、インデックス指定すればbasename( )
と同じ結果を出せる。
>>> print(os.path.split(files[4])[1]) text05.txt
パスとファイル名の分離は、for
文を使って各ファイル名ごとに行う。
>>> files = glob.glob('**/*.txt', recursive=True) >>> name = [os.path.basename(f) for f in files] #各ファイル名にbasename( )をかける >>> print(name) ['text01.txt', 'text02.txt', 'text03.txt', 'text04.txt', 'text05.txt', 'text06.txt']
最終的にサブフォルダを含めたファイル名だけを取得することができた。 問題はこのファイルに何をするか。