Jak używać glob () do rekurencyjnego znajdowania plików?
Oto co mam:
glob(os.path.join('src','*.c'))
Ale chcę przeszukać podfoldery src. Coś takiego by działało:
glob(os.path.join('src','*.c'))
glob(os.path.join('src','*','*.c'))
glob(os.path.join('src','*','*','*.c'))
glob(os.path.join('src','*','*','*','*.c'))
Ale to jest oczywiście ograniczone i niezgrabne. 28 answers
Pathlib./ Align = "left" / rglob
Użycie pathlib.Path.rglob
z the pathlib
moduł, który został wprowadzony w Pythonie 3.5.
from pathlib import Path
for path in Path('src').rglob('*.c'):
print(path.name)
Jeśli nie chcesz używać pathlib, Użyj glob.glob('**/*.c')
, ale nie zapomnij podać parametru słowa kluczowego recursive
i będzie on zużywał zbyt dużo czasu na dużych katalogach.
Dla przypadków, w których pasują pliki zaczynające się od kropki (.
); Jak pliki w bieżącym katalogu lub ukryte pliki w systemie uniksowym, użyj os.walk
rozwiązanie poniżej.
Os.spacer
Dla starszych wersji Pythona, użyj os.walk
rekurencyjnie chodzić po katalogu i fnmatch.filter
aby dopasować do wyrażenia prostego:
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))
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-09-05 16:02:15
Podobne do innych rozwiązań, ale za pomocą fnmatch.fnmatch zamiast glob, od os.walk już wymienione nazwy plików:
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
Ponadto, korzystanie z generatora pozwala przetwarzać każdy plik tak, jak został znaleziony, zamiast znajdować wszystkie pliki , a następnie przetwarzać je.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-11-23 11:00:57
Zmodyfikowałem moduł glob do obsługi * * rekurencyjnego globbingu, np:
>>> import glob2
>>> all_header_files = glob2.glob('src/**/*.c')
Https://github.com/miracle2k/python-glob2/
Przydatne, gdy chcemy zapewnić użytkownikom możliwość używania składni**, a tym samym systemu operacyjnego.sam spacer () to za mało.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-14 19:40:54
Począwszy od Pythona 3.4, można użyć glob()
metoda jednej z klas Path
w nowym module pathlib , który obsługuje symbole wieloznaczne **
. Na przykład:
from pathlib import Path
for file_path in Path('src').glob('**/*.c'):
print(file_path) # do whatever you need with these files
Aktualizacja:
Począwszy od Pythona 3.5, ta sama składnia jest również obsługiwana przez glob.glob()
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-19 09:13:25
Dla Pythona >= 3.5 możesz użyć **
, recursive=True
:
import glob
for x in glob.glob('/path/**/*.c', recursive=True):
print(x)
Jeśli rekurencyjny jest
True
, Wzór**
dopasuje dowolne pliki i zero lub więcejdirectories
isubdirectories
. Jeśli po wzorze następuje anos.sep
, tylko katalogi isubdirectories
pasują.
Uwaga:
Python3.6
wydaje się domyślne recursive=True
Podczas używania **
, więc można go pominąć.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-11-30 04:32:23
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
daje dokładnie takie same wzory jak glob
, więc jest to naprawdę doskonały zamiennik glob.glob
z bardzo bliską semantyką. Wersja iteracyjna (np. generator), zastępująca glob.iglob
, jest trywialną adaptacją (po prostu yield
pośrednie wyniki na bieżąco, zamiast extend
w pojedynczej liście wyników do powrotu na końcu).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-09 10:02:02
Będziesz chciał użyć os.walk
do zbierania nazw plików spełniających Twoje kryteria. Na przykład:
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))
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-02 18:24:48
Oto rozwiązanie z zagnieżdżonym składaniem list, os.walk
i prostym dopasowaniem przyrostków zamiast 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')]
Można ją skompresować do jednoliniowej:
import os;cfiles=[os.path.join(r,f) for r,d,fs in os.walk('src') for f in fs if f.endswith('.c')]
Lub uogólnione jako funkcja:
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')
Jeśli potrzebujesz pełnych glob
wzorców stylów, możesz podążać za Alex i
Przykład i użycie 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')
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-10 17:38:57
Rozważ pathlib.rglob()
.
To jest jak wywołanie
Path.glob()
z"**/"
dodanym przed podanym wzorem względnym:
import pathlib
for p in pathlib.Path("src").rglob("*.c"):
print(p)
Zobacz także pokrewny post tutaj i podobny post gdzie indziej.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-10-22 12:06:31
Ostatnio musiałem odzyskać moje zdjęcia z rozszerzeniem ..jpg Uruchomiłem photorec i odzyskałem 4579 katalogów 2,2 miliona plików wewnątrz, mając ogromną różnorodność rozszerzeń.Za pomocą poniższego skryptu udało mi się wybrać 50133 plików .rozszerzenie jpg w ciągu kilku minut:
#!/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)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-05 10:59:28
Na podstawie innych odpowiedzi jest to moja obecna implementacja, która pobiera zagnieżdżone pliki xml w katalogu głównym:
files = []
for root, dirnames, filenames in os.walk(myDir):
files.extend(glob.glob(root + "/*.xml"))
Naprawdę dobrze się bawię z Pythonem:)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-07-28 22:09:23
Johan i Bruno zapewniają doskonałe rozwiązania w zakresie minimalnych wymagań, jak stwierdzono. Właśnie wydałem Formic , który implementuje Ant FileSet i Globs, które poradzą sobie z tym i bardziej skomplikowanymi scenariuszami. Implementacja twojego wymogu to:
import formic
fileset = formic.FileSet(include="/src/**/*.c")
for file_name in fileset.qualified_files():
print file_name
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-15 09:14:13
Dla Pythona 3.5 i nowszych
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)
Dalej możesz potrzebować
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'
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-11-21 08:55:15
import os, glob
for each in glob.glob('path/**/*.c', recursive=True):
print(f'Name with path: {each} \nName without path: {os.path.basename(each)}')
-
glob.glob('*.c')
: dopasowuje wszystkie pliki kończące się.c
w bieżącym katalogu -
glob.glob('*/*.c')
: to samo co 1 -
glob.glob('**/*.c')
: dopasowuje wszystkie pliki kończące się.c
tylko w bezpośrednich podkatalogach, ale nie w bieżącym katalogu -
glob.glob('*.c',recursive=True)
: to samo co 1 -
glob.glob('*/*.c',recursive=True)
: to samo co 3 -
glob.glob('**/*.c',recursive=True)
: dopasowuje wszystkie pliki kończące się.c
w bieżącym katalogu i we wszystkich podkatalogach
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-08-03 05:10:01
Inny sposób, aby to zrobić za pomocą modułu glob. Wystarczy zalać metodę rglob z początkowym katalogiem bazowym i wzorcem do dopasowania, a zwróci ona listę pasujących nazw plików.
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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-28 18:07:03
Lub ze zrozumieniem listy:
>>> 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") ]
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-24 10:41:03
Właśnie to zrobiłem.. będzie drukować pliki i katalog w sposób hierarchiczny
Ale nie używałem fnmatch ani 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)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-27 18:12:29
Ten używa fnmatch lub wyrażenia regularnego:
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')])
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-02 16:01:34
Oprócz sugerowanych odpowiedzi, możesz to zrobić za pomocą leniwego pokolenia i magii rozumienia listy:
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)
Oprócz dopasowania w jednej linii i unikania niepotrzebnych list w pamięci, ma to również ładny efekt uboczny, że można go używać w sposób podobny do operatora**, np. można użyć os.path.join(root, 'some/path/*.c')
, Aby uzyskać wszystkie .pliki c we wszystkich podkatalogach src, które mają tę strukturę.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-05 17:42:56
Uproszczona wersja odpowiedzi Johana Dahlina, Bez 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']
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-03 01:29:07
Oto moje rozwiązanie wykorzystujące zrozumienie listy do wyszukiwania Wielu rozszerzeń plików rekurencyjnie w katalogu i wszystkich podkatalogach:
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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-18 17:50:33
Jest to działający kod w Pythonie 2.7. W ramach prac nad devops musiałem napisać skrypt, który przenosiłby pliki konfiguracyjne oznaczone live-appName.właściwości do nazwy aplikacji.właściwości. Mogą istnieć również inne pliki rozszerzeń, takie jak live-appName.xml.
Poniżej znajduje się działający do tego kod, który znajduje pliki w podanych katalogach (poziom zagnieżdżony), a następnie zmienia je (przenosi) na wymaganą nazwę pliku
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)
Ta funkcja jest wywoływana z głównego script
flipProperties(searchDir)
Mam nadzieję, że pomoże to komuś zmagającemu się z podobnymi problemami.Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-04-03 10:10:40
Na wypadek, gdyby to kogoś zainteresowało, sprofilowałem trzy najlepsze proponowane metody. Mam około ~500K plików w folderze globbed (w sumie) i 2K plików, które pasują do pożądanego wzorca.
Oto (bardzo podstawowy) kod
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)
A wyniki jakie otrzymałem były:
os_walk: ~3.6 sec
rglob ~14.5 sec
iglob: ~16.9 sek
Platforma: Ubuntu 16.04, x86_64 (core i7),
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-09-07 15:49:11
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)
Zmodyfikowałem pierwszą odpowiedź w tym wpisie.. a ostatnio stworzony skrypt, który będzie przeszukiwał wszystkie pliki w danym katalogu (searchdir) i podkatalogi pod nim... i wyświetla nazwę pliku, rootdir, datę modyfikacji/utworzenia i rozmiar.
Mam nadzieję, że to komuś pomoże... i mogą przejść przez katalog i uzyskać fileinfo.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))
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-15 13:39:49
Oto rozwiązanie, które dopasuje wzorzec do pełnej ścieżki, a nie tylko podstawowej nazwy pliku.
Używa fnmatch.translate
Aby przekonwertować wzorzec stylu glob na wyrażenie regularne, które jest następnie dopasowywane do pełnej ścieżki KAŻDEGO pliku znalezionego podczas chodzenia po katalogu.
re.IGNORECASE
jest opcjonalne, ale pożądane w systemie Windows, ponieważ sam system plików nie uwzględnia wielkości liter. (Nie zawracałem sobie głowy kompilacją regex, ponieważ dokumenty wskazują, że powinno być buforowane wewnętrznie.)
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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-30 15:39:36
Jeśli pliki znajdują się w zdalnym systemie plików lub wewnątrz archiwum , możesz użyć implementacji klasy Fsspec AbstractFileSystem . Na przykład, aby wyświetlić listę wszystkich plików w pliku zipfile:
from fsspec.implementations.zip import ZipFileSystem
fs = ZipFileSystem("/tmp/test.zip")
fs.glob("/**") # equivalent: fs.find("/")
Lub wyświetlenie wszystkich plików w publicznie dostępnym zasobniku S3:
from s3fs import S3FileSystem
fs_s3 = S3FileSystem(anon=True)
fs_s3.glob("noaa-goes16/ABI-L1b-RadF/2020/045/**") # or use fs_s3.find
Możesz go również użyć dla lokalnego systemu plików, co może być interesujące, jeśli twoja implementacja powinna być system-agnostic:
from fsspec.implementations.local import LocalFileSystem
fs = LocalFileSystem()
fs.glob("/tmp/test/**")
Inne implementacje to Google Cloud, Github, SFTP/SSH, Dropbox i Azure. Więcej informacji można znaleźć w dokumentacji API fsspec .Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-10-08 13:49:14
Potrzebowałem rozwiązania dla Pythona 2.x , który działa szybko na dużych katalogach.
Kończę z tym:
import subprocess
foundfiles= subprocess.check_output("ls src/*.c src/**/*.c", shell=True)
for foundfile in foundfiles.splitlines():
print foundfile
Zauważ, że możesz potrzebować obsługi wyjątków w przypadku, gdy ls
nie znajdzie pasującego pliku.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-23 10:20:37