web-dev-qa-db-ja.com

ディレクトリ内のファイルのフィルタリストを取得する

Pythonを使用してディレクトリ内のファイルのリストを取得しようとしていますが、すべてのファイルのリストを取得したくありません。

私が本質的に欲しいのは、以下のような、しかしPythonを使用し、lsを実行しないようなことをする能力です。

ls 145592*.jpg

このための組み込みメソッドがない場合は、os.listdir()の結果を繰り返し処理し、一致するすべてのファイルを新しいリストに追加するためのforループを作成することを現在検討しています。

しかし、そのディレクトリにはたくさんのファイルがあるので、もっと効率的な方法(または組み込みの方法)があるといいのですが。

224
mhost
312

glob.glob()は間違いなくそれを行う方法です(Ignacioによると)。しかし、もっと複雑なマッチングが必要な場合は、リスト内包表記とre.match()を使って行うことができます。

files = [f for f in os.listdir('.') if re.match(r'[0-9]+.*\.jpg', f)]

より柔軟ですが、ご存知のように効率が悪くなります。

108
Ben Hoyt

複雑にしないでおく:

import os
relevant_path = "[path to folder]"
included_extensions = ['jpg','jpeg', 'bmp', 'png', 'gif']
file_names = [fn for fn in os.listdir(relevant_path)
              if any(fn.endswith(ext) for ext in included_extensions)]

私はこの形式のリスト内包表記が好きです。なぜならそれは英語でよく読めるからです。

私は4行目を次のように読んだ。私のパスのos.listdirの中のそれぞれのfnに対して、私の含まれている拡張子のどれにでもマッチするものだけを私に与えなさい。

初心者のpythonプログラマーにとって、フィルタリングにリスト内包表記を使うことに慣れるのは難しいかもしれません。そして、非常に大きなデータセットに対してはいくらかのメモリオーバーヘッドを持つことができます。文書化可能なコード.

このデザインに関する唯一のことは、リストの代わりに文字列を渡すことを間違えてもあなたを守らないということです。たとえば、誤って文字列をリストに変換して、その文字列のすべての文字をチェックすることになると、大量の誤検知が発生する可能性があります。

しかし、理解するのが難しい解決策よりも解決が簡単な問題を抱えているほうが良いです。

36
ramsey0

別のオプション:

>>> import os, fnmatch
>>> fnmatch.filter(os.listdir('.'), '*.py')
['manage.py']

https://docs.python.org/3/library/fnmatch.html

30
Risadinha

予備コード

import glob
import fnmatch
import pathlib
import os

pattern = '*.py'
path = '.'

解決策1 - "glob"を使う

# lookup in current dir
glob.glob(pattern)

In [2]: glob.glob(pattern)
Out[2]: ['wsgi.py', 'manage.py', 'tasks.py']

解決策2 - "os" + "fnmatch"を使う

Variant 2.1 - 現在のディレクトリでの検索

# lookup in current dir
fnmatch.filter(os.listdir(path), pattern)

In [3]: fnmatch.filter(os.listdir(path), pattern)
Out[3]: ['wsgi.py', 'manage.py', 'tasks.py']

Variant 2.2 - ルックアップ再帰

# lookup recursive
for dirpath, dirnames, filenames in os.walk(path):

    if not filenames:
        continue

    Pythonic_files = fnmatch.filter(filenames, pattern)
    if Pythonic_files:
        for file in Pythonic_files:
            print('{}/{}'.format(dirpath, file))

結果

./wsgi.py
./manage.py
./tasks.py
./temp/temp.py
./apps/diaries/urls.py
./apps/diaries/signals.py
./apps/diaries/actions.py
./apps/diaries/querysets.py
./apps/library/tests/test_forms.py
./apps/library/migrations/0001_initial.py
./apps/polls/views.py
./apps/polls/formsets.py
./apps/polls/reports.py
./apps/polls/admin.py

解決策3 - "pathlib"を使う

# lookup in current dir
path_ = pathlib.Path('.')
Tuple(path_.glob(pattern))

# lookup recursive
Tuple(path_.rglob(pattern))

ノート:

  1. Python 3.4でテスト済み
  2. モジュール "pathlib"はPython 3.4でのみ追加されました
  3. Python 3.5はglob.glob https://docs.python.org/3.5/library/glob.html#glob.glob を使った再帰的検索の機能を追加しました。私のマシンはPython 3.4でインストールされているので、私はそれをテストしていません。
8
Seti Volkylany

os.walkを使ってファイルを再帰的にリストする

import os
root = "/home"
pattern = "145992"
alist_filter = ['jpg','bmp','png','gif'] 
path=os.path.join(root,"mydir_to_scan")
for r,d,f in os.walk(path):
    for file in f:
        if file[-3:] in alist_filter and pattern in file:
            print os.path.join(root,file)
8
ghostdog74

globモジュールでフィルタリングする:

グロブをインポート

import glob

ワイルドカード:

files=glob.glob("data/*")
print(files)

Out:

['data/ks_10000_0', 'data/ks_1000_0', 'data/ks_100_0', 'data/ks_100_1',
'data/ks_100_2', 'data/ks_106_0', 'data/ks_19_0', 'data/ks_200_0', 'data/ks_200_1', 
'data/ks_300_0', 'data/ks_30_0', 'data/ks_400_0', 'data/ks_40_0', 'data/ks_45_0', 
'data/ks_4_0', 'data/ks_500_0', 'data/ks_50_0', 'data/ks_50_1', 'data/ks_60_0', 
'data/ks_82_0', 'data/ks_lecture_dp_1', 'data/ks_lecture_dp_2']

より拡張子の.txt

files = glob.glob("/home/ach/*/*.txt")

一文字

glob.glob("/home/ach/file?.txt")

番号範囲

glob.glob("/home/ach/*[0-9]*")

アルファベット範囲

glob.glob("/home/ach/[a-c]*")
5
pink.slash
import os

dir="/path/to/dir"
[x[0]+"/"+f for x in os.walk(dir) for f in x[2] if f.endswith(".jpg")]

これはあなたにそれらのフルパスでjpgファイルのリストを与えるでしょう。ファイル名だけでx[0]+"/"+ffに置き換えることができます。 f.endswith(".jpg")を任意の文字列条件に置き換えることもできます。

2
EvgenijM86

あなたはまた、より高水準のアプローチを好むかもしれません(私はfindtoolsとして実装しパッケージ化しています):

from findtools.find_files import (find_files, Match)


# Recursively find all *.txt files in **/home/**
txt_files_pattern = Match(filetype='f', name='*.txt')
found_files = find_files(path='/home', match=txt_files_pattern)

for found_file in found_files:
    print found_file

と一緒にインストールすることができます

pip install findtools
2

"path/to/images"に "jpg"と "png"の拡張子が付いたファイル名:

import os
accepted_extensions = ["jpg", "png"]
filenames = [fn for fn in os.listdir("path/to/images") if fn.split(".")[-1] in accepted_extensions]
1
gypsy

Subprocess.check_ouput()を次のように使用できます。

import subprocess

list_files = subprocess.check_output("ls 145992*.jpg", Shell=True) 

もちろん、引用符の間の文字列はシェルで実行したいものなら何でもかまいません。そして出力を保存します。

0
David A.