ディレクトリ内のファイルのフィルタリングされたリストを取得する
-
19-09-2019 - |
質問
Python を使用してディレクトリ内のファイルのリストを取得しようとしていますが、すべてのファイルのリストは必要ありません。
私が本質的に望んでいるのは、ls を実行せずに Python を使用して次のようなことを実行できる機能です。
ls 145592*.jpg
これを行うための組み込みメソッドがない場合は、現在、実行結果を反復処理する for ループを作成することを考えています。 os.listdir()
そして、一致するすべてのファイルを新しいリストに追加します。
ただし、そのディレクトリには多数のファイルがあるため、より効率的な方法 (または組み込みの方法) があることを期待しています。
他のヒント
glob.glob()
は間違いなく(イグナシオあたりとして)それを行う方法です。あなたがより複雑なマッチングを行う必要がある場合は、あなたがそのようなリスト内包とre.match()
、何かでそれを行うことができます:
files = [f for f in os.listdir('.') if re.match(r'[0-9]+.*\.jpg', f)]
より柔軟な、しかし、あなたは注意して、効率が悪くます。
単純にする:
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 プログラマにとって、フィルタリングにリスト内包表記を使用することに実際に慣れるのは難しいかもしれません。また、非常に大きなデータ セットの場合はメモリのオーバーヘッドが発生する可能性がありますが、ディレクトリのリストやその他の単純な文字列フィルタリング タスクの場合は、リスト内包表記を使用するとよりクリーンな処理が可能になります。文書化可能なコード。
この設計の唯一の点は、リストの代わりに文字列を渡すという間違いを防ぐことができないことです。たとえば、誤って文字列をリストに変換し、文字列のすべての文字をチェックすることになった場合、大量の誤検知が発生する可能性があります。
しかし、理解するのが難しい解決策よりも、簡単に解決できる問題がある方が良いのです。
別のオプションます:
>>> import os, fnmatch
>>> fnmatch.filter(os.listdir('.'), '*.py')
['manage.py']
再帰的に
あなたのファイルを一覧表示する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)
暫定コード
import glob
import fnmatch
import pathlib
import os
pattern = '*.py'
path = '.'
解決策 1 - 「グロブ」を使用する
# lookup in current dir
glob.glob(pattern)
In [2]: glob.glob(pattern)
Out[2]: ['wsgi.py', 'manage.py', 'tasks.py']
解決策 2 - 「os」+「fnmatch」を使用します
バリアント 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']
バリアント 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 - 「パスライブラリ」を使用する
# lookup in current dir
path_ = pathlib.Path('.')
tuple(path_.glob(pattern))
# lookup recursive
tuple(path_.rglob(pattern))
ノート:
- Python 3.4でテスト済み
- モジュール「pathlib」はPython 3.4でのみ追加されました。
- Python 3.5 では、glob.glob を使用した再帰的検索の機能が追加されました。https://docs.python.org/3.5/library/glob.html#glob.glob. 。私のマシンには Python 3.4 がインストールされているため、テストしていません。
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']
Fiter拡張.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]*")
あなたはまた、より高いレベルのアプローチのように(私が実装したととしてパッケージの 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
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]+"/"+f
でf
を置き換えることができます。また、あなたが望むものは何でも、文字列条件でf.endswith(".jpg")
を置き換えることができます。
ファイル名:
import os
accepted_extensions = ["jpg", "png"]
filenames = [fn for fn in os.listdir("path/to/images") if fn.split(".")[-1] in accepted_extensions]
あなたが使用することができます pathlib のPythonの標準ライブラリで提供されている3.4と上記ます。
from pathlib import Path
files = [f for f in Path.cwd().iterdir() if f.match("145592*.jpg")]
は、
としてsubprocess.check_ouput()を使用することができますimport subprocess
list_files = subprocess.check_output("ls 145992*.jpg", shell=True)
はもちろん、引用符の間の文字列を使用して、シェルで実行し、出力を保存する何もすることができます。