Tengo un directorio con un montón de archivos dentro: eee2314
, asd3442
... y eph
.
Quiero excluir todos los archivos que comienzan eph
con la glob
función.
¿Cómo puedo hacerlo?
Tengo un directorio con un montón de archivos dentro: eee2314
, asd3442
... y eph
.
Quiero excluir todos los archivos que comienzan eph
con la glob
función.
¿Cómo puedo hacerlo?
Respuestas:
Las reglas de patrón para glob no son expresiones regulares. En cambio, siguen las reglas de expansión de ruta estándar de Unix. Hay sólo unos pocos caracteres especiales: se admiten dos comodines diferentes y rangos de caracteres [de glob ].
De modo que puede excluir algunos archivos con patrones.
Por ejemplo, para excluir archivos de manifiesto (archivos que comienzan con _
) con glob, puede usar:
files = glob.glob('files_path/[!_]*')
eph
pero pueden comenzar con cualquier otra cosa. [!e][!p][!h]
filtrará los archivos que comiencen con, eee
por ejemplo.
Puede deducir conjuntos:
set(glob("*")) - set(glob("eph*"))
set(glob("*")) - set(glob("eph*"))
(y observe * al final de "eph *")
list(set(glob("*")) - set(glob("eph")))
No puede excluir patrones con la glob
función, los globs solo permiten patrones de inclusión . La sintaxis globbing es muy limitada (incluso una [!..]
clase de carácter debe coincidir con un carácter, por lo que es un patrón de inclusión para cada carácter que no está en la clase).
Tendrá que hacer su propio filtrado; una lista de comprensión suele funcionar bien aquí:
files = [fn for fn in glob('somepath/*.txt')
if not os.path.basename(fn).startswith('eph')]
iglob
aquí para evitar almacenar la lista completa en la memoria
iglob
produce listas de todos modos ; todo lo que hace es evaluar perezosamente el filtro. No ayudará a reducir la huella de memoria.
os.listdir()
resultado se mantiene en la memoria mientras itera. Pero somepath/*.txt
tiene que leer todos los nombres de archivo en un directorio en la memoria, luego reducir esa lista a solo aquellos que coincidan.
glob.glob(x) = list(glob.iglob(x))
. No es una gran sobrecarga, pero es bueno saberlo.
Tarde en el juego, pero también puedes aplicar una pitón filter
al resultado de glob
:
files = glob.iglob('your_path_here')
files_i_care_about = filter(lambda x: not x.startswith("eph"), files)
o reemplazando el lambda con una búsqueda de expresiones regulares apropiada, etc.
EDITAR: Me acabo de dar cuenta de que si está utilizando rutas completas startswith
, no funcionará, por lo que necesitaría una expresión regular
In [10]: a
Out[10]: ['/some/path/foo', 'some/path/bar', 'some/path/eph_thing']
In [11]: filter(lambda x: not re.search('/eph', x), a)
Out[11]: ['/some/path/foo', 'some/path/bar']
¿Qué tal si se salta el archivo en particular mientras se itera sobre todos los archivos de la carpeta? El siguiente código omitiría todos los archivos de Excel que comienzan con 'eph'
import glob
import re
for file in glob.glob('*.xlsx'):
if re.match('eph.*\.xlsx',file):
continue
else:
#do your stuff here
print(file)
De esta manera, puede usar patrones de expresiones regulares más complejos para incluir / excluir un conjunto particular de archivos en una carpeta.
Comparar con glob
, recomiendo pathlib
, filtrar un patrón es muy simple.
from pathlib import Path
p = Path(YOUR_PATH)
filtered = [x for x in p.glob("**/*") if not x.name.startswith("eph")]
y si desea filtrar un patrón más complejo, puede definir una función para hacer eso, como:
def not_in_pattern(x):
return (not x.name.startswith("eph")) and not x.name.startswith("epi")
filtered = [x for x in p.glob("**/*") if not_in_pattern(x)]
use ese código, puede filtrar todos los archivos que comienzan con eph
o comienzan con epi
.
De manera más general, para excluir archivos que no cumplen con algunas expresiones regulares de shell, puede usar el módulo fnmatch
:
import fnmatch
file_list = glob('somepath')
for ind, ii in enumerate(file_list):
if not fnmatch.fnmatch(ii, 'bash_regexp_with_exclude'):
file_list.pop(ind)
Lo anterior generará primero una lista a partir de una ruta determinada y luego mostrará los archivos que no satisfagan la expresión regular con la restricción deseada.
Como se menciona en la respuesta aceptada, no puede excluir patrones con glob, por lo que el siguiente es un método para filtrar su resultado glob.
La respuesta aceptada es probablemente la mejor forma pitónica de hacer las cosas, pero si crees que las listas de comprensión se ven un poco feas y quieres que tu código sea lo más numpythonic de todos modos (como hice yo), entonces puedes hacer esto (pero ten en cuenta que probablemente sea menos eficiente que el método de comprensión de listas):
import glob
data_files = glob.glob("path_to_files/*.fits")
light_files = np.setdiff1d( data_files, glob.glob("*BIAS*"))
light_files = np.setdiff1d(light_files, glob.glob("*FLAT*"))
(En mi caso, tenía algunos marcos de imagen, marcos de sesgo y marcos planos en un directorio y solo quería los marcos de imagen)
Si la posición del carácter no es importante, es decir, por ejemplo, para excluir archivos de manifiesto (donde sea que se encuentre _
) con glob
y re
- operaciones de expresión regular , puede usar:
import glob
import re
for file in glob.glob('*.txt'):
if re.match(r'.*\_.*', file):
continue
else:
print(file)
O de una manera más elegante - list comprehension
filtered = [f for f in glob.glob('*.txt') if not re.match(r'.*\_.*', f)]
for mach in filtered:
print(mach)
Puede utilizar el siguiente método:
# Get all the files
allFiles = glob.glob("*")
# Files starting with eph
ephFiles = glob.glob("eph*")
# Files which doesnt start with eph
noephFiles = []
for file in allFiles:
if file not in ephFiles:
noephFiles.append(file)
# noepchFiles has all the file which doesnt start with eph.
Thank you.