回答:
Python 3.5以降
新しいpythonを使用pathlib.Path.rglob
しているので、pathlib
モジュールから使用する必要があります。
from pathlib import Path
for path in Path('src').rglob('*.c'):
print(path.name)
pathlibを使用したくない場合は、を使用しますglob.glob
が、recursive
keywordパラメータを渡すことを忘れないでください。
一致するファイルがドット(。)で始まる場合。現在のディレクトリのファイルやUnixベースのシステムの隠しファイルのように、os.walk
以下のソリューションを使用します。
古いPythonバージョン
古いバージョンのPythonでは、を使用os.walk
してディレクトリを再帰的にウォークfnmatch.filter
し、単純な式と照合します。
import fnmatch
import os
matches = []
for root, dirnames, filenames in os.walk('src'):
for filename in fnmatch.filter(filenames, '*.c'):
matches.append(os.path.join(root, filename))
os.path.walk()
廃止されており、Pythonの3で削除されました
pathlib.Path('src').glob('**/*.c')
はずです。
他のソリューションと同様ですが、os.walkがすでにファイル名をリストしているため、globの代わりにfnmatch.fnmatchを使用します。
import os, fnmatch
def find_files(directory, pattern):
for root, dirs, files in os.walk(directory):
for basename in files:
if fnmatch.fnmatch(basename, pattern):
filename = os.path.join(root, basename)
yield filename
for filename in find_files('src', '*.c'):
print 'Found C source:', filename
また、ジェネレータを使用すると、すべてのファイルを見つけて処理するのではなく、各ファイルを見つけたときに処理することができます。
reduce(lambda x, y: x+y, map(lambda (r,_,x):map(lambda f: r+'/'+f, filter(lambda f: fnmatch.fnmatch(f, pattern), x)), os.walk('src/webapp/test_scripts')))
(os.path.join(root,filename) for root, dirs, files in os.walk(directory) for filename in files if fnmatch.fnmatch(filename, pattern))
再帰的グロビングの**をサポートするようにglobモジュールを変更しました。例:
>>> import glob2
>>> all_header_files = glob2.glob('src/**/*.c')
https://github.com/miracle2k/python-glob2/
**構文を使用する機能をユーザーに提供したい場合に役立ちます。したがって、os.walk()だけでは十分ではありません。
**
公式グロブモジュールと、実行しますglob(path, recursive=True)
Python 3.4 以降では、ワイルドカードをサポートする新しいpathlibモジュールのクラスglob()
の1つのメソッドを使用できます。例えば:Path
**
from pathlib import Path
for file_path in Path('src').glob('**/*.c'):
print(file_path) # do whatever you need with these files
更新:
Python 3.5以降、同じ構文がでもサポートされていglob.glob()
ます。
import os
import fnmatch
def recursive_glob(treeroot, pattern):
results = []
for base, dirs, files in os.walk(treeroot):
goodfiles = fnmatch.filter(files, pattern)
results.extend(os.path.join(base, f) for f in goodfiles)
return results
fnmatch
はとまったく同じパターンを提供するglob
ので、これはglob.glob
非常に厳密なセマンティクスを持つの優れた代替品です。反復バージョン(例えば、ジェネレーター)、IOWの代わりglob.iglob
は、簡単な適応です(単一の結果リストを最後に返すのではyield
なく、途中の結果だけですextend
)。
recursive_glob(pattern, treeroot='.')
編集で提案したように使用することについてどう思いますか?このようにして、たとえばrecursive_glob('*.txt')
の構文と同じように呼び出すことができ、の構文と直感的に一致しますglob
。
fnmatch.filter
に一致しますglob.glob
。これは、単一引数に一致する可能性とほぼ同じくらい便利です。
Python用> = 3.5あなたが使用することができ**
、recursive=True
:
import glob
for x in glob.glob('path/**/*.c', recursive=True):
print(x)
再帰的である
True
場合、パターン**
はすべてのファイルと0個以上directories
と一致しますsubdirectories
。パターンの後にが続く場合はos.sep
、ディレクトリとsubdirectories
一致のみです。
ネストされたリスト内包表記を使用した解決策を次に示しos.walk
ます。代わりに単純なサフィックスマッチングを使用しglob
ます。
import os
cfiles = [os.path.join(root, filename)
for root, dirnames, filenames in os.walk('src')
for filename in filenames if filename.endswith('.c')]
ワンライナーに圧縮できます:
import os;cfiles=[os.path.join(r,f) for r,d,fs in os.walk('src') for f in fs if f.endswith('.c')]
または関数として一般化:
import os
def recursive_glob(rootdir='.', suffix=''):
return [os.path.join(looproot, filename)
for looproot, _, filenames in os.walk(rootdir)
for filename in filenames if filename.endswith(suffix)]
cfiles = recursive_glob('src', '.c')
完全なglob
スタイルパターンが必要な場合は、AlexとBrunoの例に従い、次を使用できますfnmatch
。
import fnmatch
import os
def recursive_glob(rootdir='.', pattern='*'):
return [os.path.join(looproot, filename)
for looproot, _, filenames in os.walk(rootdir)
for filename in filenames
if fnmatch.fnmatch(filename, pattern)]
cfiles = recursive_glob('src', '*.c')
最近、拡張子.jpgを付けて写真を復元する必要がありました。私はphotorecを実行し、膨大な種類の拡張子を持つ4579ディレクトリ内の220万のファイルを回復しました。以下のスクリプトを使用して、50133ファイルのhavin .jpg拡張子を数分で選択できました。
#!/usr/binenv python2.7
import glob
import shutil
import os
src_dir = "/home/mustafa/Masaüstü/yedek"
dst_dir = "/home/mustafa/Genel/media"
for mediafile in glob.iglob(os.path.join(src_dir, "*", "*.jpg")): #"*" is for subdirectory
shutil.copy(mediafile, dst_dir)
考えてくださいpathlib.rglob()
。
これは、呼び出しのようなものである
Path.glob()
と"**/"
指定した相対的なパターンの前に追加しました:
import pathlib
for p in pathlib.Path("src").rglob("*.c"):
print(p)
述べたように、ヨハンとブルーノは最小限の要件で優れたソリューションを提供します。私は、この複雑なシナリオを処理できるAnt FileSetとGlobsを実装するFormicをリリースしました。要件の実装は次のとおりです。
import formic
fileset = formic.FileSet(include="/src/**/*.c")
for file_name in fileset.qualified_files():
print file_name
他の回答に基づいて、これは私の現在機能している実装であり、ルートディレクトリ内のネストされたxmlファイルを取得します。
files = []
for root, dirnames, filenames in os.walk(myDir):
files.extend(glob.glob(root + "/*.xml"))
私は本当にpythonを楽しんでいます:)
globモジュールだけを使用する別の方法。開始ベースディレクトリと一致するパターンをrglobメソッドにシードするだけで、一致するファイル名のリストが返されます。
import glob
import os
def _getDirs(base):
return [x for x in glob.iglob(os.path.join( base, '*')) if os.path.isdir(x) ]
def rglob(base, pattern):
list = []
list.extend(glob.glob(os.path.join(base,pattern)))
dirs = _getDirs(base)
if len(dirs):
for d in dirs:
list.extend(rglob(os.path.join(base,d), pattern))
return list
Python 3.5以降の場合
import glob
#file_names_array = glob.glob('path/*.c', recursive=True)
#above works for files directly at path/ as guided by NeStack
#updated version
file_names_array = glob.glob('path/**/*.c', recursive=True)
さらに必要になるかもしれません
for full_path_in_src in file_names_array:
print (full_path_in_src ) # be like 'abc/xyz.c'
#Full system path of this would be like => 'path till src/abc/xyz.c'
/**
ように機能しますfile_names_array = glob.glob('src/**/*.c', recursive=True)
これを作成しました..ファイルとディレクトリを階層的に出力します
しかし、私はfnmatchやwalkを使用しませんでした
#!/usr/bin/python
import os,glob,sys
def dirlist(path, c = 1):
for i in glob.glob(os.path.join(path, "*")):
if os.path.isfile(i):
filepath, filename = os.path.split(i)
print '----' *c + filename
elif os.path.isdir(i):
dirname = os.path.basename(i)
print '----' *c + dirname
c+=1
dirlist(i,c)
c-=1
path = os.path.normpath(sys.argv[1])
print(os.path.basename(path))
dirlist(path)
これはfnmatchまたは正規表現を使用します。
import fnmatch, os
def filepaths(directory, pattern):
for root, dirs, files in os.walk(directory):
for basename in files:
try:
matched = pattern.match(basename)
except AttributeError:
matched = fnmatch.fnmatch(basename, pattern)
if matched:
yield os.path.join(root, basename)
# usage
if __name__ == '__main__':
from pprint import pprint as pp
import re
path = r'/Users/hipertracker/app/myapp'
pp([x for x in filepaths(path, re.compile(r'.*\.py$'))])
pp([x for x in filepaths(path, '*.py')])
提案された回答に加えて、遅延生成とリスト理解魔法を使用してこれを行うことができます:
import os, glob, itertools
results = itertools.chain.from_iterable(glob.iglob(os.path.join(root,'*.c'))
for root, dirs, files in os.walk('src'))
for f in results: print(f)
これは、1行に収めてメモリ内の不要なリストを回避するだけでなく、**演算子と同様の方法で使用できるというすばらしい副作用もあります。たとえば、os.path.join(root, 'some/path/*.c')
すべての.cファイルをすべて取得するために使用できます。この構造を持つsrcのサブディレクトリ。
これはPython 2.7で動作するコードです。開発作業の一環として、live-appName.propertiesでマークされた構成ファイルをappName.propertiesに移動するスクリプトを作成する必要がありました。live-appName.xmlのような他の拡張ファイルが存在する可能性があります。
以下は、このための作業コードです。これは、指定されたディレクトリ(ネストされたレベル)でファイルを見つけ、必要なファイル名に名前を変更(移動)します。
def flipProperties(searchDir):
print "Flipping properties to point to live DB"
for root, dirnames, filenames in os.walk(searchDir):
for filename in fnmatch.filter(filenames, 'live-*.*'):
targetFileName = os.path.join(root, filename.split("live-")[1])
print "File "+ os.path.join(root, filename) + "will be moved to " + targetFileName
shutil.move(os.path.join(root, filename), targetFileName)
この関数はメインスクリプトから呼び出されます
flipProperties(searchDir)
これが同様の問題に苦しんでいる誰かを助けることを願っています。
リスト内包表記を使用してディレクトリとすべてのサブディレクトリで複数のファイル拡張子を再帰的に検索する私の解決策は次のとおりです。
import os, glob
def _globrec(path, *exts):
""" Glob recursively a directory and all subdirectories for multiple file extensions
Note: Glob is case-insensitive, i. e. for '\*.jpg' you will get files ending
with .jpg and .JPG
Parameters
----------
path : str
A directory name
exts : tuple
File extensions to glob for
Returns
-------
files : list
list of files matching extensions in exts in path and subfolders
"""
dirs = [a[0] for a in os.walk(path)]
f_filter = [d+e for d in dirs for e in exts]
return [f for files in [glob.iglob(files) for files in f_filter] for f in files]
my_pictures = _globrec(r'C:\Temp', '\*.jpg','\*.bmp','\*.png','\*.gif')
for f in my_pictures:
print f
私はこの投稿のトップアンサーを変更しました。最近、このスクリプトを作成しました。このスクリプトは、特定のディレクトリ(searchdir)とその下のサブディレクトリにあるすべてのファイルをループし、ファイル名、rootdir、変更/作成日、およびサイズ。
これが誰かを助けることを願っています...そして彼らはディレクトリを歩いてファイル情報を得ることができます。
import time
import fnmatch
import os
def fileinfo(file):
filename = os.path.basename(file)
rootdir = os.path.dirname(file)
lastmod = time.ctime(os.path.getmtime(file))
creation = time.ctime(os.path.getctime(file))
filesize = os.path.getsize(file)
print "%s**\t%s\t%s\t%s\t%s" % (rootdir, filename, lastmod, creation, filesize)
searchdir = r'D:\Your\Directory\Root'
matches = []
for root, dirnames, filenames in os.walk(searchdir):
## for filename in fnmatch.filter(filenames, '*.c'):
for filename in filenames:
## matches.append(os.path.join(root, filename))
##print matches
fileinfo(os.path.join(root, filename))
これは、ベースファイル名だけでなく、フルパスに対してパターンを照合するソリューションです。
これはfnmatch.translate
、globスタイルのパターンを正規表現に変換するために使用します。正規表現は、ディレクトリを歩くときに見つかった各ファイルの完全パスと照合されます。
re.IGNORECASE
オプションですが、Windowsではファイルシステム自体で大文字と小文字が区別されないため、これが望ましいです。(ドキュメントは内部的にキャッシュする必要があることをドキュメントが示しているので、私は正規表現をコンパイルする気になりませんでした。)
import fnmatch
import os
import re
def findfiles(dir, pattern):
patternregex = fnmatch.translate(pattern)
for root, dirs, files in os.walk(dir):
for basename in files:
filename = os.path.join(root, basename)
if re.search(patternregex, filename, re.IGNORECASE):
yield filename
大規模なディレクトリで高速に動作するpython 2.xのソリューションが必要でした。
私はこれで終わります:
import subprocess
foundfiles= subprocess.check_output("ls src/*.c src/**/*.c", shell=True)
for foundfile in foundfiles.splitlines():
print foundfile
ls
一致するファイルが見つからない場合は、例外処理が必要になる場合があることに注意してください。
os.path.walk()
よりも、使用にはもう少し手間のかかるあるos.walk()