from - glob python install
Python glob mĂșltiples tipos de archivos (23)
¿Hay alguna forma mejor de usar glob.glob en python para obtener una lista de varios tipos de archivos como .txt, .mdown y .markdown? En este momento 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'') )
Aquí hay una variante de comprensión de lista de una línea de la respuesta de Pat (que también incluye que usted quería englobar 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))]
Usted for ext in exts
las extensiones ( for ext in exts
), y luego para cada extensión toma cada archivo que coincida con el patrón glob ( for f in glob.glob(os.path.join(project_dir, ext)
).
Esta solución es corta y sin bucles for innecesarios, comprensiones de listas anidadas o funciones que atestan el código. Solo Zen puro, expresivo y pitónico.
Esta solución le permite tener una lista personalizada de exts
que se puede cambiar sin tener que actualizar su código. (¡Esta es siempre una buena práctica!)
La comprensión de la lista es la misma utilizada en la solución de Laurent (que he votado). Pero yo diría que generalmente no es necesario factorizar una sola línea en una función separada, razón por la cual estoy proporcionando esto como una solución alternativa.
Prima:
Si necesita buscar no solo un directorio, sino también todos los subdirectorios, puede pasar recursive=True
y usar el símbolo global de multi-directorio **
1 :
files = [f for ext in exts
for f in glob.glob(os.path.join(project_dir, ''**'', ext), recursive=True)]
Esto invocará glob.glob(''<project_dir>/**/*.txt'', recursive=True)
y así sucesivamente para cada extensión.
1 Técnicamente, el símbolo **
glob simplemente coincide con uno o más caracteres, incluida la barra diagonal /
(a diferencia del singular *
símbolo glob). En la práctica, solo necesita recordar que siempre que rodee **
con barras diagonales (separadores de ruta), coincide con cero o más directorios.
Después de venir aquí en busca de ayuda, hice mi propia solución y quería compartirla. Se basa en la respuesta de user2363986, pero creo que es más escalable. Es decir, si tienes 1000 extensiones, el código aún se verá algo 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
Encadena 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
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 archivo que comienzan con ~
.
Esto debería funcionar:
import glob
extensions = (''*.txt'', ''*.mdown'', ''*.markdown'')
for i in extensions:
for files in glob.glob(i):
print (files)
He lanzado Formic que implementa múltiples incluye 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 Ant glob completo, puede incluir diferentes directorios con cada patrón, por lo que puede elegir solo los archivos .txt en un subdirectorio y el .markdown en otro, por ejemplo:
patterns = [ "/unformatted/**/*.txt", "/formatted/**/*.mdown" ]
Espero que esto ayude.
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")
No es glob
, pero esta es 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]
Para glob
varios 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 puede usar glob.iglob()
para tener un iterador:
Devuelve un iterador que produce 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)))
Podría usar filter:
import os
import glob
projectFiles = filter(
lambda x: os.path.splitext(x)[1] in [".txt", ".mdown", ".markdown"]
glob.glob(os.path.join(projectDir, "*"))
)
Por ejemplo, para *.mp3
y *.flac
en varias carpetas, puede hacer:
mask = r''music/*/*.[mf][pl][3a]*''
glob.glob(mask)
La idea se puede extender a más extensiones de archivo, pero debe verificar que las combinaciones no coincidan con ninguna otra extensión de archivo no deseado que pueda tener en esas carpetas. Por lo tanto, ten cuidado con esto.
Puede tratar de hacer una lista manual comparando la extensión 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)
Tal vez hay una mejor manera, pero ¿qué tal?
>>> 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
Tal vez haya otra forma, así que espere en caso de que alguien encuentre una mejor respuesta.
También podrías 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.
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))
Un globo, muchas extensiones ... pero una solución imperfecta (podría 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)
Un trazador de líneas, solo por el placer 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'']
con glob no es posible. solo puedes usar:
* coincide con todo
? coincide con cualquier personaje
[seq] coincide con cualquier carácter en seq
[! seq] coincide con cualquier carácter 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
esto funcionó para mí:
import glob
images = glob.glob(''*.JPG'' or ''*.jpg'' or ''*.png'')
glob
devuelve una lista: ¿por qué no simplemente ejecutarlo varias veces y concatenar los resultados?
from glob import glob
ProjectFiles = glob(''*.txt'') + glob(''*.mdown'') + glob(''*markdown'')
files = glob.glob(''*.txt'')
files.extend(glob.glob(''*.dat''))
from glob import glob
files = glob(''*.gif'')
files.extend(glob(''*.png''))
files.extend(glob(''*.jpg''))
print(files)
Si necesita especificar una ruta, repita los patrones de coincidencia y mantenga la combinación dentro del ciclo 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)
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