Python glob múltiples tipos de archivos

¿Existe una mejor manera de usar glob.glob en python para obtener una lista de varios tipos de archivos como .txt, .mdown y .markdown? Ahora mismo tengo algo como esto:

projectFiles1 = glob.glob( os.path.join(projectDir, '*.txt') ) projectFiles2 = glob.glob( os.path.join(projectDir, '*.mdown') ) projectFiles3 = glob.glob( os.path.join(projectDir, '*.markdown') ) 

Related of "Python glob múltiples tipos de archivos"

Tal vez hay una mejor manera, pero ¿qué hay de:

 >>> import glob >>> types = ('*.pdf', '*.cpp') # the tuple of file types >>> files_grabbed = [] >>> for files in types: ... files_grabbed.extend(glob.glob(files)) ... >>> files_grabbed # the list of pdf and cpp files 

Quizás haya otra forma, así que espere en caso de que alguien más encuentre una mejor respuesta.

 from glob import glob files = glob('*.gif') files.extend(glob('*.png')) files.extend(glob('*.jpg')) print(files) 

Si necesita especificar una ruta, haga un bucle sobre los patrones de coincidencia y mantenga la unión dentro del bucle para simplificar:

 from os.path import join from glob import glob files = [] for ext in ('*.gif', '*.png', '*.jpg'): files.extend(glob(join("path/to/dir", ext))) print(files) 

Encadenar los resultados:

 import itertools as it, glob def multiple_file_types(*patterns): return it.chain.from_iterable(glob.iglob(pattern) for pattern in patterns) 

Entonces:

 for filename in multiple_file_types("*.txt", "*.sql", "*.log"): # do stuff 

glob devuelve una lista: ¿por qué no solo ejecutarlo varias veces y concatenar los resultados?

 from glob import glob ProjectFiles = glob('*.txt') + glob('*.mdown') + glob('*markdown') 

Con glob no es posible. puedes usar solo:
* coincide con todo
? coincide con cualquier carácter individual
[seq] coincide con cualquier caracter en seq
[! seq] coincide con cualquier personaje que no esté en seq

use os.listdir y una expresión regular para verificar patrones:

 for x in os.listdir('.'): if re.match('.*\.txt|.*\.sql', x): print x 

Por ejemplo, para *.mp3 y *.flac en varias carpetas, puede hacer:

 mask = r'music/*/*.[mf][pl][3a]*' glob.glob(mask) 

La idea puede extenderse a más extensiones de archivo, pero debe verificar que las combinaciones no coincidirán con ninguna otra extensión de archivo no deseada que pueda tener en esas carpetas. Por lo tanto, tenga cuidado con esto.

Después de venir aquí en busca de ayuda, hice mi propia solución y quise compartirla. Se basa en la respuesta de user2363986, pero creo que esto es más escalable. Lo que significa que si tienes 1000 extensiones, el código seguirá pareciendo un tanto elegante.

 from glob import glob directoryPath = "C:\\temp\\*." fileExtensions = [ "jpg", "jpeg", "png", "bmp", "gif" ] listOfFiles = [] for extension in fileExtensions: listOfFiles.extend( glob( directoryPath + extension )) for file in listOfFiles: print(file) # Or do other stuff 

Una sola frase, sólo por el gusto de hacerlo ..

 folder = "C:\\multi_pattern_glob_one_liner" files = [item for sublist in [glob.glob(folder + ext) for ext in ["/*.txt", "/*.bat"]] for item in sublist] 

salida:

 ['C:\\multi_pattern_glob_one_liner\\dummy_txt.txt', 'C:\\multi_pattern_glob_one_liner\\dummy_bat.bat'] 

Esta es una solución Python 3.4+ pathlib :

 exts = ".pdf", ".doc", ".xls", ".csv", ".ppt" filelist = (str(i) for i in map(pathlib.Path, os.listdir(src)) if i.suffix.lower() in exts and not i.stem.startswith("~")) 

También ignora todos los nombres de archivos que comienzan con ~ .

Aquí hay una variante de comprensión de lista de una línea de la respuesta de Pat (que también incluye lo que deseaba incluir en un directorio de proyecto específico):

 import os, glob exts = ['*.txt', '*.mdown', '*.markdown'] files = [f for ext in exts for f in glob.glob(os.path.join(project_dir, ext))] 

for ext in exts por las extensiones ( for ext in exts ), y luego para cada extensión, tome cada archivo que coincida con el patrón glob ( for f in glob.glob(os.path.join(project_dir, ext) ).

Esta solución es breve y sin ningún tipo de for-loops, listas de comprensión anidadas o funciones innecesarias para saturar el código. Solo puro, expresivo, zen pythonico.

Esta solución le permite tener una lista personalizada de exts que se pueden cambiar sin tener que actualizar su código. (¡Esta es siempre una buena práctica!)

La lista de comprensión es la misma que se utiliza en la solución de Laurent (por la que he votado). Pero diría que generalmente no es necesario factorizar una sola línea para una función separada, por lo que ofrezco esto como una solución alternativa.

Prima:

Si necesita buscar no solo en un solo directorio, sino también en todos los subdirectorios, puede pasar recursive=True y usar el símbolo global de varios directorios ** 1 :

 files = [f for ext in exts for f in glob.glob(os.path.join(project_dir, '**', ext), recursive=True)] 

Esto invocará glob.glob('/**/*.txt', recursive=True) y así sucesivamente para cada extensión.

1 Técnicamente, el símbolo ** glob simplemente se corresponde con uno o más caracteres, incluida la barra diagonal hacia adelante / (a diferencia del símbolo glob * singular). En la práctica, solo debe recordar que siempre que rodee ** con barras diagonales (separadores de ruta), coincida con cero o más directorios.

He liberado Formic, que implementa varias aplicaciones de manera similar a FileSet y Globs de Apache Ant.

La búsqueda puede ser implementada:

 import formic patterns = ["*.txt", "*.markdown", "*.mdown"] fileset = formic.FileSet(directory=projectDir, include=patterns) for file_name in fileset.qualified_files(): # Do something with file_name 

Debido a que se implementa el globo Ant completo, puede incluir diferentes directorios con cada patrón, por lo que puede elegir solo esos archivos .txt en un subdirectorio, y el .markdown en otro, por ejemplo:

 patterns = [ "/unformatted/**/*.txt", "/formatted/**/*.mdown" ] 

Espero que esto ayude.

No glob , pero aquí hay otra forma de usar una lista de comprensión:

 extensions = 'txt mdown markdown'.split() projectFiles = [f for f in os.listdir(projectDir) if os.path.splitext(f)[1][1:] in extensions] 

La siguiente función _glob globs para múltiples extensiones de archivo.

 import glob import os def _glob(path, *exts): """Glob for multiple file extensions Parameters ---------- path : str A file name without extension, or directory name exts : tuple File extensions to glob for Returns ------- files : list list of files matching extensions in exts in path """ path = os.path.join(path, "*") if os.path.isdir(path) else path + "*" return [f for files in [glob.glob(path + ext) for ext in exts] for f in files] files = _glob(projectDir, ".txt", ".mdown", ".markdown") 
 files = glob.glob('*.txt') files.extend(glob.glob('*.dat')) 

Para glob múltiples tipos de archivos, necesita llamar a la función glob() varias veces en un bucle. Como esta función devuelve una lista, debe concatenar las listas.

Por ejemplo, esta función hace el trabajo:

 import glob import os def glob_filetypes(root_dir, *patterns): return [path for pattern in patterns for path in glob.glob(os.path.join(root_dir, pattern))] 

Uso simple:

 project_dir = "path/to/project/dir" for path in sorted(glob_filetypes(project_dir, '*.txt', '*.mdown', '*.markdown')): print(path) 

También puedes usar glob.iglob() para tener un iterador:

Devuelva un iterador que produzca los mismos valores que glob () sin almacenarlos todos simultáneamente.

 def iglob_filetypes(root_dir, *patterns): return (path for pattern in patterns for path in glob.iglob(os.path.join(root_dir, pattern))) 

Puede intentar hacer una lista manual comparando la extensión de la existente con las que necesita.

 ext_list = ['gif','jpg','jpeg','png']; file_list = [] for file in glob.glob('*.*'): if file.rsplit('.',1)[1] in ext_list : file_list.append(file) 

Podrías usar filtro:

 import os import glob projectFiles = filter( lambda x: os.path.splitext(x)[1] in [".txt", ".mdown", ".markdown"] glob.glob(os.path.join(projectDir, "*")) ) 

También puedes usar reduce() manera:

 import glob file_types = ['*.txt', '*.mdown', '*.markdown'] project_files = reduce(lambda list1, list2: list1 + list2, (glob.glob(t) for t in file_types)) 

esto crea una lista de glob.glob() para cada patrón y los reduce a una sola lista.

 import os import glob import operator from functools import reduce types = ('*.jpg', '*.png', '*.jpeg') lazy_paths = (glob.glob(os.path.join('my_path', t)) for t in types) paths = reduce(operator.add, lazy_paths, []) 

https://docs.python.org/3.5/library/functools.html#functools.reduce https://docs.python.org/3.5/library/operator.html#operator.add

Un globo, muchas extensiones … pero una solución imperfecta (puede coincidir con otros archivos).

 filetypes = ['tif', 'jpg'] filetypes = zip(*[list(ft) for ft in filetypes]) filetypes = ["".join(ch) for ch in filetypes] filetypes = ["[%s]" % ch for ch in filetypes] filetypes = "".join(filetypes) + "*" print(filetypes) # => [tj][ip][fg]* glob.glob("/path/to/*.%s" % filetypes) 

Tuve el mismo problema y esto es lo que se me ocurrió

 import os, sys, re #without glob src_dir = '/mnt/mypics/' src_pics = [] ext = re.compile('.*\.(|{}|)$'.format('|'.join(['png', 'jpeg', 'jpg']).encode('utf-8'))) for root, dirnames, filenames in os.walk(src_dir): for filename in filter(lambda name:ext.search(name),filenames): src_pics.append(os.path.join(root, filename)) 

Por ejemplo:

 import glob lst_img = [] base_dir = '/home/xy/img/' # get all the jpg file in base_dir lst_img += glob.glob(base_dir + '*.jpg') print lst_img # ['/home/xy/img/2.jpg', '/home/xy/img/1.jpg'] # append all the png file in base_dir to lst_img lst_img += glob.glob(base_dir + '*.png') print lst_img # ['/home/xy/img/2.jpg', '/home/xy/img/1.jpg', '/home/xy/img/3.png'] 

Una función:

 import glob def get_files(base_dir='/home/xy/img/', lst_extension=['*.jpg', '*.png']): """ :param base_dir:base directory :param lst_extension:lst_extension: list like ['*.jpg', '*.png', ...] :return:file lists like ['/home/xy/img/2.jpg','/home/xy/img/3.png'] """ lst_files = [] for ext in lst_extension: lst_files += glob.glob(base_dir+ext) return lst_files 

Use una lista de extensiones y repita

 from os.path import join from glob import glob files = ['*.gif', '*.png', '*.jpg'] for ext in files: files.extend(glob(join("path/to/dir", ext))) print(files) 

Otra solución más (use glob para obtener rutas usando múltiples patterns coincidencia y combine todas las rutas en una sola lista usando reduce y add ):

 import functools, glob, operator paths = functools.reduce(operator.add, [glob.glob(pattern) for pattern in [ "path1/*.ext1", "path2/*.ext2"]]) 

Esto debería funcionar:

 import glob extensions = ('*.txt', '*.mdown', '*.markdown') for i in extensions: for files in glob.glob(i): print (files) 

esto funcionó para mí:

 import glob images = glob.glob('*.JPG' or '*.jpg' or '*.png')