Pythonのglobの賢い使い方【パス収集】

167, 2021-01-25

目次

Pythonのglobの賢い使い方

Pythonにはパスを収集するライブラリ「glob(グロブ)」があります。
このglobを使うとファイルシステム上から簡単にファイルのパスを収集することが出来ます。

スポンサーリンク

パターンによるマッチを行うので直観的にパスを収集可能です。

この記事ではglobを賢く使う方法を解説します。
具体的には↓を見ていきます。

  • globの概要
  • globの構造
  • globでディレクトリを得る
  • globで複数のファイルを集める
  • globで再帰的にすべてのファイルを集める

globの概要

globはPythonの標準ライブラリの1つです。
glob.glob()はファイルシステム上からファイルのパスを収集する関数です。
収集のさいにパターンによるマッチングを行うので、特定の拡張子を持っているファイルのみを集めるなどの芸当が可能です。

glob.glob()を使うにはglobモジュールを↓のようにインポートします。

import glob

あとはglobモジュール内のglob()関数を使えばパスの収集が可能です。

globモジュールにはglob()の他にもiglob()escape()などの関数があります。
iglob()glob()が返り値をリストで返すのに対して、返り値をジェネレーターで返します。
escape()はパスに含まれる(?, *, [)などの特殊文字をエスケープする関数です。

glob.glob()の構造

glob()は↓のような構造を持っています。

glob.glob(pathname, *, recursive=False)

glob()は最大で3つの引数を取り、1つの返り値を返します。

pathname(第1引数)

収集したいファイルのパターンを指定します。

パターンは絶対パスと相対パスによる記述が可能です。
絶対パスは例えば↓のようになります。

/path/to/file.txt

相対パスは↓のようになります。

to/file.txt

たとえばパターンが「img/*.png」であれば、glob()imgディレクトリ以下から拡張子がpngのファイルを収集します。
パターンが「img/*.jpg」であればjpgのファイルを収集します。
このようにglob()ではシェルスタイルのワイルドカードを使うことが出来ます。
正規表現ではなくシェル由来のワイルドカードである点に注意が必要です。

*(第2引数)

詳細は不明です。

recursive(第3引数)

pathname**であるとき、このrecursiveTrueにすると、glob()はパターンのパスを基点に再帰的にパスを収集します。
特定のディレクトリ以下のファイルやディレクトリをすべてリストとして取得したい場合などに有効なオプションです。
これを使うと網羅的にファイルのパスを収集できます。

ただしディレクトリの階層が深い場合は処理に時間がかかることが予想されます。
使う際はその点に注意が必要です。

globのパターンに指定できる展開記法

glob()の第1引数に指定するパターンはシェル由来のワイルドカードを指定できます。

ワイルドカード 一致対象
 ? 任意の一文字
 * 任意の文字列
 [set] set の中のいずれかの文字
 [!set] set の中のいずれでもない文字

(参考: 1. bash の基礎

任意の1文字

?を使うと、任意の1文字にマッチさせることができます。
たとえば↓のパターンは

file.?

↓のファイルにマッチします。

file.c     file.h    file.o

任意の文字列

*を使うと任意の文字列にマッチさせることができます。
たとえば↓のパターンは

my-*.txt

↓のファイルにマッチします。

my-cat.txt    my-dog.txt    my-bird.txt

setの中のいずれかの文字

[set]を使うと[]で囲まれたいずれかの文字にマッチさせることができます。
たとえば↓のパターンは

file-[ab].txt

↓のファイルにマッチします。

file-a.txt    file-b.txt

setの中のいずれでもない文字

[!set]を使うと[!]の中のいずれでもない文字にマッチさせることができます。
たとえば↓のパターンは

file-[!ab].txt

↓のファイルなどにマッチします。

file-x.txt    file-y.txt

解説に使うディレクトリ構造

今回は↓のようなディレクトリとファイルを解説に使います。

$ tree animals/
animals/
├── cat
│   ├── mikeneko.jpg
│   └── mikeneko.png
└── dog
    ├── chiwawa.jpg
    └── chiwawa.png

2 directories, 4 files

globでディレクトリを得る

glob()でディレクトリを取得するには↓のようにディレクトリ名を指定します。

import glob

files = glob.glob('animals')
print(files)

↑のコードの出力結果は↓のようになります。

['animals']

しかしパスをベタ書きするのであれば、そのパスを使えばいいので↑のようなコードはあまりglobの利点が目立っていません。

globで複数のファイルを集める

glob()で複数のファイルを集める場合は↓のようにワイルドカードを使います。

import glob

files = glob.glob('animals/*')
print(files)

↑のコードの出力結果は↓のようになります。

['animals/cat', 'animals/dog']

↑の出力結果を見ると、animals/直下のディレクトリが収集できているのがわかります。
再帰的には収集していない点に注意が必要です。
再帰的に収集したい場合は後述の「globで再帰的にすべてのファイルを集める」をご覧ください。

また、特定の拡張子のファイルを収集したい場合は↓のようにします。

import glob

files = glob.glob('animals/cat/*.png')
print(files)

↑のコードの出力結果は↓のようになります。

['animals/cat/mikeneko.png']

globで再帰的にすべてのファイルを集める

パターンに**を指定し、recursiveTrueにするとglob()はパスを再帰的に収集します。

import glob

files = glob.glob('**', recursive=True)
print(files)

↑のコードの出力結果は↓のようになります。

['animals', 'animals/cat', 'animals/cat/mikeneko.jpg', 'animals/cat/mikeneko.png', 'animals/dog', 'animals/dog/chiwawa.jpg', 'animals/dog/chiwawa.png', 'sample.py']

sample.pyは↑のスクリプトです。
↑の出力を見るとanimals/ディレクトリを再帰的に下って行ってファイルのパスを取得しているのがわかります。

おわりに

今回はPythonのライブラリglobの使い方を解説しました。
globはPythonのパワーを感じられる良いライブラリだと思います。
特定のディレクトリ以下のパスをまとめて取得したい時に威力を発揮するライブラリです。


スポンサーリンク

投稿者名です。64字以内で入力してください。

必要な場合はEメールアドレスを入力してください(全体に公開されます)。

投稿する内容です。