Unixなどのシェルをよく使うことがある人はご存知だと思いますが、コマンドの引数にワイルドカードを使ったパターン(文字列)を指定して、複数のファイルを一括して扱うことができます。
例えば、次のコマンドはシェルがワイルドカードを含む「*.txt」というパターンを認識し、そのパターンにマッチするファイル名に展開(この例の場合、bar.txt baz.txt foo.txtに展開)してからシェルはlsコマンドを実行します。
$ ls *.txt
bar.txt baz.txt foo.txt
つまり展開された後、次のようにlsコマンは実行されています。
$ ls bar.txt baz.txt foo.txt
このようなシェルの機能はグロブ(あるいはファイルグロブ)と呼ばれます。
Pythonにもパターン文字列をそれにマッチするファイル名に展開する機能が提供されています。この機能を適用する主要なモジュールはglobモジュールです。この記事ではPythonでこのグロブを使う機能について解説していきます。
シェルのグロブ(ワイルドカード)については次の記事が参考になります。
ワイルドカードの種類
Pythonのパターン文字列に使用できるワイルドカードは次のものがあります。これらの使い方もシェルと同じなので馴染みがあるかもしれません。
構文 | 説明 |
---|---|
* | 0個以上の任意の文字列にマッチする |
? | 任意の1文字にマッチする |
[abc] | []の中の任意の1文字にマッチする(この例ではa、b、cのいずれかの文字にマッチする) |
[!abc] | []の中の文字以外にマッチする(この例ではa、b、c以外の文字にマッチする) |
パターンにマッチするファイルを一覧する
globモジュールのglob()関数を使うと、引数のパターン文字列にマッチするファイルを一覧することができます。glob()はパターンにマッチしたファイルをリストで返します。パターンは絶対パスまたはカレントディレクトリに対する相対パスのいずれでも構いません。
次の例はカレントディレクトリの全てのファイルを一覧します。
>>> glob.glob('*')
['linkdir', 'dir1', 'dir2', 'cat.txt', 'bat.txt', 'rat.txt', 'hat.py']
次の例は「.txt」を拡張子に持つファイルを一覧します。glob()は引数のパターンにマッチしたファイルを一覧するので、パターンの指定の仕方によって返される結果のファイル名も異なることに注意してください。
>>> glob.glob('*.txt')
['cat.txt', 'bat.txt', 'rat.txt']
>>> glob.glob('./*.txt')
['./cat.txt', './bat.txt', './rat.txt']
>>> glob.glob('/home/taro/testdir/*.txt')
['/home/taro/testdir/cat.txt', '/home/taro/testdir/bat.txt', '/home/taro/testdir/rat.txt']
「?」をを使った例を示します。
>>> glob.glob('?at.txt')
['cat.txt', 'bat.txt', 'rat.txt']
>>> glob.glob('?at.*')
['cat.txt', 'bat.txt', 'rat.txt', 'hat.py']
[abc]、[!abc]を使った例を示します。
>>> glob.glob('[!abc]at.txt')
['rat.txt']
>>> glob.glob('[!abc]at.*')
['rat.txt', 'hat.py']
隠しファイルにマッチさせる
glob()関数は通常、隠しファイル(ドットで始まるファイル)にはマッチしません。ドットで始まるファイルは、同じくドットで始まるパターンにのみマッチします。
>>> glob.glob('*.txt')
['cat.txt', 'bat.txt', 'rat.txt']
>>> glob.glob('.*.txt')
['.hidden.txt']
root_dir引数
root_dir引数を指定(デフォルトはNone)した場合は、相対パスの基準はカレントディレクトリではなくroot_dir引数に指定されたディレクトリが基準になります。これは、root_dir引数のディレクトリにカレントディレクトリを変更した後、glob()を呼び出すのと等価です。
>>> glob.glob('*.txt', root_dir='dir1')
['file1.txt', 'file2.txt']
パターンにマッチするファイルを順に一覧する
glob.iglob()関数は、引数のパターン文字列にマッチするファイル名を順に生成するジェネレータオブジェクトを返すので、ファイル名を1つずつ処理するのに便利です。
>>> for entry in glob.iglob('*.txt'):
... entry
...
'cat.txt'
'bat.txt'
'rat.txt'
iglob()にはglob()と同様に、root_dir引数も指定できます。
>>> for entry in glob.iglob('*.txt', root_dir='dir1'):
... entry
...
'file1.txt'
'file2.txt'
pathlibモジュールのglob()メソッド
pathlibモジュールで定義されている具象パスクラスでもglob()メソッドが提供されています。このglob()メソッドもglob.iglob()と同様にジェネレータオブジェクトを返します。
ただし、このジェネレータオブジェクトが順に生成するのはマッチしたファイルを表す具象パスのオブジェクトです。
>>> from pathlib import Path
>>> p = Path()
>>> for entry in p.glob('*.txt'):
... entry
...
PosixPath('cat.txt')
PosixPath('bat.txt')
PosixPath('rat.txt')
PosixPath('.hidden.txt')
まとめ
グロブは正規表現のように、1つのパターン文字列で複数のファイルを扱う方法です。シェルで使ってなかった方は、是非この機会に学んでみてはいかがでしょうか。グロブはシェルの機能なので、コマンドラインではいつでも使うことができます。
では、最後までお読みいただき誠にありがとうございます。