アメリエフの技術ブログ

Amelieff Staff Blog

globでパスのリストを取得

kimotonです。
RのカテゴリーはあるのにPythonのカテゴリーないのですね、、勝手に作りました。

パスの取得は、パイプライン開発なんかの際によく必要になります。 Pythonの標準ライブラリglob を使えば、正規表現を使ってパスのリストが取得できちゃいます!

基本的な使い方

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

pathnameの箇所に取得したいパスを正規表現で打つだけ。 パスは相対パスでも絶対パスでも入ります。
例えば、/usr/binディレクトリ以下のpythonから始まるファイルパスを得たいときは

>>> glob.glob("/usr/bin/python*")
['/usr/bin/python',
 '/usr/bin/python-config',
 '/usr/bin/python2',
 '/usr/bin/python2-config',
 '/usr/bin/python2.7',
 '/usr/bin/python2.7-config',
 '/usr/bin/python3',
 '/usr/bin/python3-config',
 '/usr/bin/python3-jsondiff',
 '/usr/bin/python3-jsonpatch',
 '/usr/bin/python3-jsonpointer',
 '/usr/bin/python3.5',
 '/usr/bin/python3.5-config',
 '/usr/bin/python3.5m',
 '/usr/bin/python3.5m-config',
 '/usr/bin/python3m',
 '/usr/bin/python3m-config']

いっぱいありますね。

ファイルの数が多い!

正規表現で当たっちゃうファイル数がめちゃめちゃ多い。
リストで格納するには時間がかかりすぎる。。

そんなあなたにiglob

これを使えばリストに格納せずに、イテレーターで返してくれます。

>>> glob.iglob("/usr/bin/python*")
<generator object _iglob at 0x7f8756a458e0>

エコですね。

サブディレクトリも含めて探したい!

これができちゃうのがglobのすごいところ。

recursive が真の場合、パターン "**" はあらゆるファイルや 0 個以上のディレクトリおよびサブディレクトリにマッチします。
引用元:11.7. glob — Unix 形式のパス名のパターン展開 — Python 3.6.5 ドキュメント

カレントディレクトリ以下の拡張子(.txt)を持つファイルのパスを取得するには

>>> glob.glob('**/*.txt', recursive=True)
['2.txt', 'sub/3.txt']

すごいですね。

応用編

最後はアメリエフらしくfastqファイルのパスを取得してみましょう。

例えば、target_dir以下のpathのリストを取得したいときは以下のように書けます。

import(os)
import(glob)
path_list = [os.path.abspath(i) for i in glob.glob("{}/**/*.fastq".format(target_dir), recursive=True)]

このようにos.path.abspath()と組み合わせれば、target_dirとして指定されたパスが絶対パスでも相対パスでも絶対パスのリストとして返してくれちゃいます。

めちゃめちゃ便利ですね。