Voici ce que j'ai
glob(os.path.join('src','*.c'))
mais je veux rechercher les sous-dossiers de src. Quelque chose comme ça marcherait:
glob(os.path.join('src','*.c'))
glob(os.path.join('src','*','*.c'))
glob(os.path.join('src','*','*','*.c'))
glob(os.path.join('src','*','*','*','*.c'))
Mais ceci est évidemment limité et maladroit.
Python 3.5+
À partir de Python version 3.5, le module glob
prend en charge la directive "**"
(qui est analysée uniquement si vous passez l'indicateur recursive
):
import glob
for filename in glob.iglob('src/**/*.c', recursive=True):
print(filename)
Si vous avez besoin d’une liste, utilisez simplement glob.glob
au lieu de glob.iglob
.
Pour les cas où les fichiers correspondants commencent par un point (.); comme des fichiers du répertoire en cours ou des fichiers cachés sur un système Unix, utilisez la solution os.walk
ci-dessous.
Python 2.2 à 3.4
Pour les anciennes versions de Python, à partir de Python 2.2, utilisez os.walk
pour parcourir de manière récursive un répertoire et fnmatch.filter
pour faire correspondre une expression simple:
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 et versions antérieures
Pour les versions encore plus anciennes de Python, utilisez glob.glob
contre chaque nom de fichier au lieu de fnmatch.filter
.
Semblable à d'autres solutions, mais en utilisant fnmatch.fnmatch au lieu de glob, puisque os.walk a déjà répertorié les noms de fichiers:
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
En outre, l’utilisation d’un générateur vous permet de traiter chaque fichier tel qu’il est trouvé, au lieu de rechercher tous les fichiers et ensuite de les traiter.
J'ai modifié le module glob afin de prendre en charge ** les modifications globales récursives, par exemple:
>>> import glob2
>>> all_header_files = glob2.glob('src/**/*.c')
https://github.com/miracle2k/python-glob2/
Utile lorsque vous souhaitez que vos utilisateurs puissent utiliser la syntaxe **. Ainsi, os.walk () seul ne suffit pas.
À partir de Python 3.4, on peut utiliser la méthode glob()
de l’une des classes Path
du nouveau module pathlib , qui prend en charge les caractères joker **
. Par exemple:
from pathlib import Path
for file_path in Path('src').glob('**/*.c'):
print(file_path) # do whatever you need with these files
Update: À partir de Python 3.5, la même syntaxe est également prise en charge par 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
vous donne exactement les mêmes modèles que glob
, donc c'est vraiment un excellent remplacement pour glob.glob
avec une sémantique très proche. Une version itérative (par exemple un générateur), qui remplace IOW par glob.iglob
, est une adaptation triviale (juste yield
les résultats intermédiaires au fur et à mesure, au lieu de extend
ing une liste de résultats unique à renvoyer à la fin).
Vous voudrez utiliser os.walk
pour collecter les noms de fichiers correspondant à vos critères. Par exemple:
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))
Voici une solution avec des compréhensions de liste imbriquées, os.walk
et un suffixe simple correspondant à la place de 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')]
Il peut être compressé en une ligne:
import os;cfiles=[os.path.join(r,f) for r,d,fs in os.walk('src') for f in fs if f.endswith('.c')]
ou généralisé en fonction:
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')
Si vous avez besoin de modèles de style glob
complets, vous pouvez suivre l'exemple d'Alex et Bruno et utiliser 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')
Récemment, j'ai dû récupérer mes photos avec l'extension .jpg. J'ai couru photorec et récupéré 4579 répertoires dans 2,2 millions de fichiers, avec une grande variété d'extensions. Avec le script ci-dessous, j'ai pu sélectionner 50133 fichiers avec l'extension .jpg en quelques minutes:
#!/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 et Bruno apportent d’excellentes solutions aux exigences minimales énoncées. Je viens de publier Formic qui implémente Ant FileSet et Globs qui peuvent gérer cela et des scénarios plus compliqués. Une implémentation de votre besoin est:
import formic
fileset = formic.FileSet(include="/src/**/*.c")
for file_name in fileset.qualified_files():
print file_name
sur la base d’autres réponses, c’est mon implémentation de travail actuelle, qui récupère les fichiers XML imbriqués dans un répertoire racine:
files = []
for root, dirnames, filenames in os.walk(myDir):
files.extend(glob.glob(root + "/*.xml"))
Je m'amuse vraiment avec python :)
Une autre façon de le faire en utilisant simplement le module glob. Ensemencez simplement la méthode rglob avec un répertoire de base de départ et un modèle de correspondance, ce qui renverra une liste de noms de fichiers correspondants.
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
En plus des réponses suggérées, vous pouvez le faire avec une magie paresseuse de la génération et de la compréhension de la liste:
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)
En plus d'insérer une ligne et d'éviter des listes inutiles en mémoire, cela a également pour effet secondaire que vous pouvez l'utiliser de la même manière que l'opérateur **, par exemple, vous pouvez utiliser os.path.join(root, 'some/path/*.c')
pour obtenir tous les fichiers .c tous les sous-répertoires de src qui ont cette structure.
Vient de faire cela .. il va imprimer les fichiers et le répertoire de manière hiérarchique
Mais je n'ai pas utilisé fnmatch ou marcher
#!/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)
Considérons pathlib.rglob()
.
C'est comme si vous appeliez
Path.glob()
avec"**/"
ajouté devant le modèle relatif donné:
import pathlib
for p in pathlib.Path("src").rglob("*.c"):
print(p)
Voir aussi @ post ici et un post _ _ précédent (taleinat) ailleurs.
Celui-là utilise fnmatch ou expression régulière:
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')])
Voici ma solution en utilisant la compréhension de liste pour rechercher plusieurs extensions de fichiers de manière récursive dans un répertoire et tous les sous-répertoires:
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
Version simplifiée de la réponse de Johan Dahlin, sans 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']
Pour python> = .5 , vous pouvez utiliser **
, recursive=True
:
import glob
for x in glob.glob('path/**/*.c', recursive=True):
print(x)
Si récursif est vrai, le modèle
**
correspond à tous les fichiers et à zéro ou plusdirectories
etsubdirectories
. Si le motif est suivi d'unos.sep
, seuls les répertoires etsubdirectories
correspondent.
Ou avec une compréhension de liste:
>>> 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") ]
Voici une solution qui fera correspondre le modèle au chemin complet et pas uniquement au nom de fichier de base.
Il utilise fnmatch.translate
pour convertir un motif de style global en une expression régulière, qui est ensuite comparée au chemin complet de chaque fichier trouvé lors de la consultation du répertoire.
re.IGNORECASE
est facultatif, mais souhaitable sous Windows car le système de fichiers lui-même n'est pas sensible à la casse. (Je n'ai pas pris la peine de compiler l'expression rationnelle car la documentation indique qu'elle devrait être mise en cache en interne.)
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
Pour python 3.5 et versions ultérieures
file_names_array = glob.glob('src/*.c', recursive=True)
Edit: Comme @NeStack guidé si ci-dessus ne fonctionne pas pour vous, s'il vous plaît essayez
file_names_array = glob.glob('src/**.c', recursive=True)
de plus vous pourriez avoir besoin
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)
J'ai modifié la première réponse dans cette publication .. et récemment créé ce script qui parcourt tous les fichiers d'un répertoire donné (searchdir) et des sous-répertoires en dessous ... Taille.
J'espère que cela aide quelqu'un ... et ils peuvent parcourir le répertoire et obtenir 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))
J'avais besoin d'une solution pour python 2.x qui fonctionne rapide sur les grands répertoires.
Je termine avec ceci:
import subprocess
foundfiles= subprocess.check_output("ls src/*.c src/**/*.c", Shell=True)
for foundfile in foundfiles.splitlines():
print foundfile
Notez que vous aurez peut-être besoin d'une gestion des exceptions au cas où ls
ne trouve aucun fichier correspondant.