Das ist was ich habe:
glob(os.path.join('src','*.c'))
aber ich möchte die Unterordner von src durchsuchen. So etwas würde funktionieren:
glob(os.path.join('src','*.c'))
glob(os.path.join('src','*','*.c'))
glob(os.path.join('src','*','*','*.c'))
glob(os.path.join('src','*','*','*','*.c'))
Dies ist jedoch offensichtlich begrenzt und klobig.
Python 3.5+
Ab der Python-Version 3.5 unterstützt das Modul glob
die "**"
-Direktive (die nur analysiert wird, wenn Sie das Flag recursive
übergeben):
import glob
for filename in glob.iglob('src/**/*.c', recursive=True):
print(filename)
Wenn Sie eine Liste benötigen, verwenden Sie einfach glob.glob
anstelle von glob.iglob
.
Für Fälle, in denen übereinstimmende Dateien mit einem Punkt beginnen (.); Verwenden Sie wie bei Dateien im aktuellen Verzeichnis oder versteckten Dateien auf Unix-basierten Systemen die Lösung os.walk
unten.
Python 2.2 bis 3.4
Bei älteren Python-Versionen, beginnend mit Python 2.2, verwenden Sie os.walk
, um ein Verzeichnis rekursiv zu durchsuchen, und fnmatch.filter
, um einen einfachen Ausdruck zu finden:
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))
Python 2.1 und früher
Für noch ältere Python-Versionen verwenden Sie glob.glob
anstelle jedes Dateinamens anstelle von fnmatch.filter
.
Ähnlich wie bei anderen Lösungen, jedoch mit fnmatch.fnmatch anstelle von glob, da os.walk bereits die Dateinamen aufführt:
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
Wenn Sie einen Generator verwenden, können Sie auch jede Datei so verarbeiten, wie sie gefunden wurde, anstatt alle Dateien und dann zu finden.
Ich habe das glob-Modul so geändert, dass es ** für rekursives Globbing unterstützt, z. B .:
>>> import glob2
>>> all_header_files = glob2.glob('src/**/*.c')
https://github.com/miracle2k/python-glob2/
Nützlich, wenn Sie Ihren Benutzern die Möglichkeit geben möchten, die ** Syntax zu verwenden, und daher ist os.walk () alleine nicht gut genug.
Ab Python 3.4 kann man die glob()
-Methode einer der Path
-Klassen im neuen pathlib - Modul verwenden, das **
-Platzhalter unterstützt. Zum Beispiel:
from pathlib import Path
for file_path in Path('src').glob('**/*.c'):
print(file_path) # do whatever you need with these files
Update: Ab Python 3.5 wird dieselbe Syntax auch von glob.glob()
unterstützt.
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
liefert genau die gleichen Muster wie glob
, daher ist dies wirklich ein hervorragender Ersatz für glob.glob
mit sehr enger Semantik. Eine iterative Version (z. B. ein Generator), IOW, ein Ersatz für glob.iglob
, ist eine triviale Anpassung (lediglich yield
die Zwischenergebnisse, während Sie fortfahren, anstatt extend
ing eine einzelne Ergebnisliste am Ende zurückzugeben).
Verwenden Sie os.walk
, um Dateinamen zu sammeln, die Ihren Kriterien entsprechen. Zum Beispiel:
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))
Hier ist eine Lösung mit verschachtelten Listenübergängen, os.walk
und einfachem Suffix-Matching anstelle von 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')]
Es kann zu einem Einzeiler komprimiert werden:
import os;cfiles=[os.path.join(r,f) for r,d,fs in os.walk('src') for f in fs if f.endswith('.c')]
oder verallgemeinert als Funktion:
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')
Wenn Sie vollständige glob
-Stilmuster benötigen, können Sie den Beispielen von Alex und Bruno folgen und fnmatch
verwenden:
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')
Vor kurzem musste ich meine Bilder mit der Erweiterung .jpg wiederherstellen. Ich habe photorec ausgeführt und 4579 Verzeichnisse innerhalb von 2,2 Millionen Dateien wiederhergestellt, die eine enorme Vielfalt an Erweiterungen haben.
#!/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)
Johan und Bruno bieten ausgezeichnete Lösungen für die genannten Mindestanforderungen. Ich habe gerade Formic veröffentlicht, das Ant FileSet und Globs implementiert , das diese und kompliziertere Szenarien verarbeiten kann. Eine Implementierung Ihrer Anforderung ist:
import formic
fileset = formic.FileSet(include="/src/**/*.c")
for file_name in fileset.qualified_files():
print file_name
basierend auf anderen Antworten ist dies meine derzeitige Implementierung, die verschachtelte XML-Dateien in einem Stammverzeichnis abruft:
files = []
for root, dirnames, filenames in os.walk(myDir):
files.extend(glob.glob(root + "/*.xml"))
Ich habe wirklich Spaß mit Python :)
Eine andere Möglichkeit, dies nur mit dem Glob-Modul zu tun. Keimen Sie einfach die rglob-Methode mit einem Ausgangsverzeichnis und einem passenden Muster, und es wird eine Liste der übereinstimmenden Dateinamen zurückgegeben.
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
Zusätzlich zu den vorgeschlagenen Antworten können Sie dies mit etwas Zaubern für das Generieren und Listenverständnis tun:
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)
Neben dem Einfügen in eine Zeile und dem Vermeiden unnötiger Listen im Speicher hat dies auch den Nebeneffekt von Nice, dass Sie ihn ähnlich wie den Operator ** verwenden können, z. B. können Sie os.path.join(root, 'some/path/*.c')
verwenden, um alle .c-Dateien zu erhalten alle Unterverzeichnisse von src, die diese Struktur haben.
Gerade gemacht .. es werden Dateien und Verzeichnisse auf hierarchische Weise gedruckt
Aber ich habe weder fnmatch noch zu Fuß benutzt
#!/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)
Betrachten Sie pathlib.rglob()
.
Dies ist wie der Aufruf von
Path.glob()
, wobei"**/"
vor dem angegebenen relativen Muster hinzugefügt wird:
import pathlib
for p in pathlib.Path("src").rglob("*.c"):
print(p)
Siehe auch @ taleinats verwandtes post hier und ein früheres post anderswo.
Dieser verwendet fnmatch oder regulären Ausdruck:
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 __== '__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')])
Hier ist meine Lösung, die das Listenverständnis für die Suche nach multiple Dateiendungen rekursiv in einem Verzeichnis und allen Unterverzeichnissen verwendet:
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
Vereinfachte Version von Johan Dahlins Antwort ohne fnmatch .
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']
Für python> = .5 können Sie **
, recursive=True
verwenden:
import glob
for x in glob.glob('path/**/*.c', recursive=True):
print(x)
Wenn rekursiv wahr ist, entspricht das Muster
**
allen Dateien und null oder mehrdirectories
undsubdirectories
. Wenn dem Muster einos.sep
folgt, stimmen nur Verzeichnisse undsubdirectories
überein.
Oder mit einem Listenverständnis:
>>> 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") ]
Hier ist eine Lösung, bei der das Muster mit dem vollständigen Pfad und nicht nur mit dem Basisdateinamen abgeglichen wird.
Es verwendet fnmatch.translate
, um ein Muster im Glob-Stil in einen regulären Ausdruck zu konvertieren, der dann mit dem vollständigen Pfad jeder gefundenen Datei abgeglichen wird, während das Verzeichnis durchsucht wird.
re.IGNORECASE
ist optional, aber unter Windows wünschenswert, da das Dateisystem selbst nicht zwischen Groß- und Kleinschreibung unterscheidet. (Ich habe mir nicht die Mühe gemacht, den Regex zu kompilieren, da die Dokumente darauf hinweisen, dass er intern zwischengespeichert werden sollte.)
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
Für python 3.5 und höher
file_names_array = glob.glob('src/*.c', recursive=True)
Bearbeiten: Als @NeStack geführt, wenn oben für Sie nicht funktioniert, versuchen Sie es bitte
file_names_array = glob.glob('src/**.c', recursive=True)
weiter könnten Sie brauchen
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'
import sys, os, glob
dir_list = ["c:\\books\\heap"]
while len(dir_list) > 0:
cur_dir = dir_list[0]
del dir_list[0]
list_of_files = glob.glob(cur_dir+'\\*')
for book in list_of_files:
if os.path.isfile(book):
print(book)
else:
dir_list.append(book)
Ich habe die oberste Antwort in diesem Beitrag geändert. Vor kurzem habe ich dieses Skript erstellt, das alle Dateien in einem bestimmten Verzeichnis (searchdir) und die darunter liegenden Unterverzeichnisse durchläuft ... und den Dateinamen, das Stammverzeichnis, das Änderungsdatum/Erstellungsdatum und Größe.
Hoffe, das hilft jemandem ... und sie können das Verzeichnis abrufen und Dateiinformationen abrufen.
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))
Ich brauchte eine Lösung für python 2.x, die fast für große Verzeichnisse unterstützt.
Ich endete damit:
import subprocess
foundfiles= subprocess.check_output("ls src/*.c src/**/*.c", Shell=True)
for foundfile in foundfiles.splitlines():
print foundfile
Beachten Sie, dass Sie möglicherweise eine Ausnahmebehandlung benötigen, falls ls
keine übereinstimmende Datei findet.