906

これは私が持っているものです:

glob(os.path.join('src','*.c'))

しかし、srcのサブフォルダーを検索したい。次のようなものが機能します。

glob(os.path.join('src','*.c'))
glob(os.path.join('src','*','*.c'))
glob(os.path.join('src','*','*','*.c'))
glob(os.path.join('src','*','*','*','*.c'))

しかし、これは明らかに限定的で扱いにくいものです。

4

28 に答える 28

1624

pathlib.Path.rglob

Python 3.5 で導入されpathlib.Path.rglobたモジュールから使用します。pathlib

from pathlib import Path

for path in Path('src').rglob('*.c'):
    print(path.name)

pathlib を使用したくない場合は、 を使用できますglob.glob('**/*.c')が、キーワード パラメータを渡すことを忘れないでくださいrecursive。大きなディレクトリでは非常に時間がかかります。

.ドット ( )で始まるファイルが一致する場合。現在のディレクトリ内のファイルや Unix ベースのシステムの隠しファイルのように、以下のos.walk解決策を使用してください。

os.walk

古いバージョンの 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))
于 2010-02-02T18:26:54.480 に答える
119

他のソリューションと同様ですが、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

また、ジェネレーターを使用すると、すべてのファイルを見つけてから処理するのではなく、見つかった各ファイルを処理することができます

于 2010-02-02T18:44:51.497 に答える
91

** をサポートするように glob モジュールを変更して、再帰的なグロビングを行いました。例:

>>> import glob2
>>> all_header_files = glob2.glob('src/**/*.c')

https://github.com/miracle2k/python-glob2/

ユーザーに ** 構文を使用できるようにしたい場合に便利で、 os.walk() だけでは十分ではありません。

于 2011-06-26T14:14:22.400 に答える
41
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

于 2010-02-02T18:39:38.597 に答える
21

os.walk基準に一致するファイル名を収集するために使用します。例えば:

import os
cfiles = []
for root, dirs, files in os.walk('src'):
  for file in files:
    if file.endswith('.c'):
      cfiles.append(os.path.join(root, file))
于 2010-02-02T18:24:48.610 に答える
16

ネストされたリスト内包表記と、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')
于 2011-11-02T08:10:45.207 に答える
7

最近、拡張子が .jpg の写真を復元する必要がありました。私は photorec を実行し、220 万個のファイルが含まれる 4,579 個のディレクトリを復元しました。以下のスクリプトを使用すると、.jpg 拡張子を持つ 50,133 個のファイルを数分で選​​択できました。

#!/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)
于 2013-01-05T10:36:43.233 に答える
6

他の回答に基づいて、これは私の現在の作業実装であり、ルートディレクトリにネストされたxmlファイルを取得します。

files = []
for root, dirnames, filenames in os.walk(myDir):
    files.extend(glob.glob(root + "/*.xml"))

私は本当にPythonを楽しんでいます:)

于 2012-07-28T22:09:23.130 に答える
6

これが誰かに興味があるかもしれない場合に備えて、提案された上位 3 つの方法を紹介しました。グロブ フォルダーには (合計で) 約 500K のファイルがあり、目的のパターンに一致する 2K のファイルがあります。

これが(非常に基本的な)コードです

import glob
import json
import fnmatch
import os
from pathlib import Path
from time import time


def find_files_iglob():
    return glob.iglob("./data/**/data.json", recursive=True)


def find_files_oswalk():
    for root, dirnames, filenames in os.walk('data'):
        for filename in fnmatch.filter(filenames, 'data.json'):
            yield os.path.join(root, filename)

def find_files_rglob():
    return Path('data').rglob('data.json')

t0 = time()
for f in find_files_oswalk(): pass    
t1 = time()
for f in find_files_rglob(): pass
t2 = time()
for f in find_files_iglob(): pass 
t3 = time()
print(t1-t0, t2-t1, t3-t2)

os_walk
: ~3.6sec
rglob ~14.5sec
iglob: ~16.9sec

プラットフォーム: Ubuntu 16.04、x86_64 (コア i7)、

于 2020-06-13T17:39:18.453 に答える
5

JohanとBrunoは、述べられているように、最小要件で優れたソリューションを提供します。これとより複雑なシナリオを処理できるAntFileSetとGlobsを実装するFormicをリリースしました。要件の実装は次のとおりです。

import formic
fileset = formic.FileSet(include="/src/**/*.c")
for file_name in fileset.qualified_files():
    print file_name
于 2012-05-15T08:53:18.170 に答える
3

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
于 2011-09-13T22:59:25.647 に答える
3

またはリスト内包表記で:

 >>> base = r"c:\User\xtofl"
 >>> binfiles = [ os.path.join(base,f) 
            for base, _, files in os.walk(root) 
            for f in files if f.endswith(".jpg") ] 
于 2013-06-24T10:41:03.190 に答える
2

提案された回答に加えて、遅延生成とリスト理解の魔法を使用してこれを行うことができます。

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 のサブディレクトリ。

于 2015-12-05T17:42:56.140 に答える
2

それは 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')])
于 2013-08-02T16:01:34.540 に答える
1

リスト内包表記を使用して、ディレクトリとすべてのサブディレクトリで複数のファイル拡張子を再帰的に検索する私のソリューションは次のとおりです。

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
于 2014-08-18T17:50:33.667 に答える
1

fnmatchなしの Johan Dahlin の回答の簡略版。

import os

matches = []
for root, dirnames, filenames in os.walk('src'):
  matches += [os.path.join(root, f) for f in filenames if f[-2:] == '.c']
于 2013-06-03T01:29:07.310 に答える
0

ベースファイル名だけでなく、フルパスに対してパターンを照合するソリューションを次に示します。

これは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
于 2015-06-30T15:39:36.753 に答える
0

この投稿の一番の回答を変更しました..そして最近、特定のディレクトリ(searchdir)とその下のサブディレクトリ内のすべてのファイルをループするこのスクリプトを作成しました...そしてファイル名、ルートディレクトリ、変更/作成日、およびサイズ。

これが誰かの役に立てば幸いです...そして、彼らはディレクトリを歩いてファイル情報を取得できます。

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))
于 2014-11-15T13:39:49.937 に答える
-1

大きなディレクトリで高速に動作するpython 2.xのソリューションが必要でした。 私はこれで終わります:

import subprocess
foundfiles= subprocess.check_output("ls src/*.c src/**/*.c", shell=True)
for foundfile in foundfiles.splitlines():
    print foundfile

ls一致するファイルが見つからない場合に備えて、例外処理が必要になる場合があることに注意してください。

于 2017-06-23T10:20:37.343 に答える