recursive files copiar archivos python path glob

files - ¿Usar un Glob() para encontrar archivos recursivamente en Python?



glob.glob python (21)

Esto es lo que tengo:

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

pero quiero buscar las subcarpetas de src. Algo como esto funcionaría:

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

Pero esto es obviamente limitado y torpe.


Acaba de hacer esto .. se imprimirán los archivos y directorios de forma jerárquica

Pero no utilicé fnmatch o 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)


Además de las respuestas sugeridas, puede hacer esto con un poco de generación perezosa y una lista de comprensión mágica:

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)

Además de encajar en una línea y evitar listas innecesarias en la memoria, esto también tiene el efecto secundario agradable, que puede usarlo de manera similar al operador **, por ejemplo, podría usar os.path.join(root, ''some/path/*.c'') para obtener todos los archivos .c en todos los subdirectorios de src que tienen esta estructura.


Aquí está mi solución usando la comprensión de lista para buscar múltiples extensiones de archivo recursivamente en un directorio y todos los subdirectorios:

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


Aquí hay una solución con listas de comprensión anidadas, os.walk y coincidencia de sufijo simple en lugar 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'')]

Se puede comprimir en una sola línea:

import os;cfiles=[os.path.join(r,f) for r,d,fs in os.walk(''src'') for f in fs if f.endswith(''.c'')]

o generalizada como una función:

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 necesita patrones de estilo glob , puede seguir el ejemplo de Alex y Bruno y usar 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'')


Aquí hay una solución que hará coincidir el patrón con la ruta completa y no solo con el nombre de archivo base.

Utiliza fnmatch.translate para convertir un patrón de estilo glob en una expresión regular, que luego se compara con la ruta completa de cada archivo encontrado mientras recorre el directorio.

re.IGNORECASE es opcional, pero deseable en Windows ya que el sistema de archivos en sí no re.IGNORECASE mayúsculas y minúsculas. (No me molesté en compilar la expresión regular porque los documentos indican que debe guardarse en caché internamente).

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


Comenzando con Python 3.4, se puede usar el método glob() de una de las clases de Path en el nuevo módulo pathlib , que admite ** comodines. Por ejemplo:

from pathlib import Path for file_path in Path(''src'').glob(''**/*.c''): print(file_path) # do whatever you need with these files

Actualización: A partir de Python 3.5, glob.glob() también admite la misma sintaxis.


He modificado el módulo glob para que sea compatible con ** para globazas recursivas, por ejemplo:

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

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

Es útil cuando desea proporcionar a sus usuarios la capacidad de usar la sintaxis **, y por lo tanto, os.walk () solo no es lo suficientemente bueno.


Johan y Bruno proporcionan excelentes soluciones en los requisitos mínimos tal como se indica. Acabo de lanzar Formic que implementa Ant FileSet y Globs que pueden manejar esto y otros escenarios más complicados. Una implementación de su requerimiento es:

import formic fileset = formic.FileSet(include="/src/**/*.c") for file_name in fileset.qualified_files(): print file_name


Modifiqué la respuesta principal en esta publicación ... y recientemente creé esta secuencia de comandos que recorrerá todos los archivos en un directorio determinado (searchdir) y los subdirectorios debajo de él ... e imprime el nombre de archivo, rootdir, fecha de creación / modificación, y tamaño.

Espero que esto ayude a alguien ... y puedan recorrer el directorio y obtener información del archivo.

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))


Necesitaba una solución para Python 2.x que funcione rápidamente en directorios grandes.
Terminé con esto:

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

Tenga en cuenta que es posible que necesite un manejo de excepciones en caso de que ls no encuentre ningún archivo coincidente.


O con una lista de comprensión:

>>> 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") ]


Otra forma de hacerlo solo con el módulo glob. Simplemente agregue el método rglob con un directorio base de inicio y un patrón para que coincida, y devolverá una lista de nombres de archivos coincidentes.

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


Que uno usa fnmatch o expresión regular:

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'')])


Recientemente tuve que recuperar mis fotos con la extensión .jpg. Corrí fotorec y recuperé 4579 directorios con 2,2 millones de archivos en el interior, con una gran variedad de extensiones. Con el siguiente script, pude seleccionar 50133 archivos con la extensión .jpg en cuestión de minutos:

#!/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)


Similar a otras soluciones, pero usando fnmatch.fnmatch en lugar de glob, ya que os.walk ya enumeró los nombres de archivo:

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

Además, el uso de un generador le permite procesar cada archivo a medida que se encuentra, en lugar de encontrar todos los archivos y luego procesarlos.


Versión simplificada de la respuesta de Johan Dahlin, sin 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'']


en base a otras respuestas, esta es mi implementación actual, que recupera archivos xml anidados en un directorio raíz:

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

Realmente me estoy divirtiendo con python :)


os.walk usar os.walk para recopilar nombres de archivos que coincidan con sus criterios. Por ejemplo:

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))


Python 3.5+

A partir de la versión 3.5 de Python, el módulo glob admite la directiva "**" (que se analiza solo si se pasa el indicador recursive ):

import glob for filename in glob.iglob(''src/**/*.c'', recursive=True): print(filename)

Si necesita una lista, solo use glob.glob lugar de glob.iglob .

Para los casos en que los archivos coincidentes comienzan con un punto (.); como archivos en el directorio actual o archivos ocultos en el sistema basado en Unix, use la solución os.walk continuación.

Python 2.2 a 3.4

Para versiones anteriores de Python, comenzando con Python 2.2, use os.walk para recorrer un directorio de forma recursiva y fnmatch.filter para que coincida con una expresión 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 y anteriores

Incluso para versiones antiguas de Python, use glob.glob contra cada nombre de archivo en lugar de fnmatch.filter .


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 te da exactamente los mismos patrones que glob , por lo que este es realmente un excelente reemplazo para glob.glob con una semántica muy cercana. Una versión iterativa (por ejemplo, un generador), glob.iglob , un reemplazo para glob.iglob , es una adaptación trivial (solo yield los resultados intermedios a medida que glob.iglob , en lugar de extend una lista de resultados única para devolver al final).


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)