Tengo un archivo que puede estar en un lugar diferente en la máquina de cada usuario. ¿Hay alguna forma de implementar una búsqueda del archivo? ¿De qué manera puedo pasar el nombre del archivo y el árbol del directorio para buscar?Buscar un archivo en python
Respuesta
os.walk es la respuesta, esta se encuentra el primer partido:
import os
def find(name, path):
for root, dirs, files in os.walk(path):
if name in files:
return os.path.join(root, name)
Y esto encontrará todas las coincidencias:
def find_all(name, path):
result = []
for root, dirs, files in os.walk(path):
if name in files:
result.append(os.path.join(root, name))
return result
Y esto va a coincidir con un patrón:
import os, fnmatch
def find(pattern, path):
result = []
for root, dirs, files in os.walk(path):
for name in files:
if fnmatch.fnmatch(name, pattern):
result.append(os.path.join(root, name))
return result
find('*.txt', '/path/to/dir')
Ver el os module para os.walk o os.listdir
Véase también esta pregunta os.walk without digging into directories below de código de ejemplo
Para una búsqueda rápida, independiente del sistema operativo, utilice scandir
https://github.com/benhoyt/scandir/#readme
Leer http://bugs.python.org/issue11406 para los detalles de por qué.
Específicamente, use 'scandir.walk() 'por la respuesta de Nadia. Tenga en cuenta que si usa Python 3.5+, 'os.walk()' ya tiene las aceleraciones 'scandir.walk()'. Además, [PEP 471] (https://www.python.org/dev/peps/pep-0471/) es probablemente un documento mejor para leer para obtener información que ese problema. –
Usé una versión de os.walk
y en un directorio más grande obtuve tiempos de aproximadamente 3,5 segundos. Probé dos soluciones al azar sin gran mejora, entonces acabo de hacer:
paths = [line[2:] for line in subprocess.check_output("find . -iname '*.txt'", shell=True).splitlines()]
Si bien es POSIX-solamente, tengo 0,25 seg.
De esto, creo que es completamente posible optimizar toda la búsqueda de una manera independiente de la plataforma, pero aquí es donde detuve la investigación.
Si está utilizando Python en Ubuntu y solo quiere que funcione en Ubuntu, una forma sustancialmente más rápida es usar el programa locate
de la terminal de esta manera.
import subprocess
def find_files(file_name):
command = ['locate', file_name]
output = subprocess.Popen(command, stdout=subprocess.PIPE).communicate()[0]
output = output.decode()
search_results = output.split('\n')
return search_results
search_results
es una list
de las rutas de archivos absolutas. Esto es 10.000 veces más rápido que los métodos anteriores y en una búsqueda que hice fue ~ 72,000 veces más rápido.
Si está trabajando con Python 2, tiene un problema con la recursión infinita en Windows causada por enlaces simbólicos autorreferenciales.
Esta secuencia de comandos evitará seguirlos. Tenga en cuenta que esto es específico de Windows!
import os
from scandir import scandir
import ctypes
def is_sym_link(path):
# http://stackoverflow.com/a/35915819
FILE_ATTRIBUTE_REPARSE_POINT = 0x0400
return os.path.isdir(path) and (ctypes.windll.kernel32.GetFileAttributesW(unicode(path)) & FILE_ATTRIBUTE_REPARSE_POINT)
def find(base, filenames):
hits = []
def find_in_dir_subdir(direc):
content = scandir(direc)
for entry in content:
if entry.name in filenames:
hits.append(os.path.join(direc, entry.name))
elif entry.is_dir() and not is_sym_link(os.path.join(direc, entry.name)):
try:
find_in_dir_subdir(os.path.join(direc, entry.name))
except UnicodeDecodeError:
print "Could not resolve " + os.path.join(direc, entry.name)
continue
if not os.path.exists(base):
return
else:
find_in_dir_subdir(base)
return hits
devuelve una lista con todos los caminos que apuntan a archivos de la lista de nombres de archivo. Uso:
find("C:\\", ["file1.abc", "file2.abc", "file3.abc", "file4.abc", "file5.abc"])
Tenga en cuenta que esto es específico de Windows – Leliel
@Leliel Lo he agregado a la respuesta. Gracias por tus comentarios. –
- 1. Python buscar en un archivo remoto usando HTTP
- 2. Buscar archivo en Xcode
- 3. Buscar cadenas duplicadas en un archivo grande
- 4. ¿Cómo buscar un archivo javascript en google?
- 5. buscar y reemplazar cadena en un archivo
- 6. Buscar y reemplazar en un archivo grande
- 7. Buscar "directorio inicial" en Python?
- 8. ¿Cómo usar Python para buscar información en latitud/longitud específica en un archivo shape de ESRI?
- 9. Buscar archivos y subcarpetas en Python
- 10. Buscar todas las referencias a un objeto en python
- 11. PHP: Cómo buscar un archivo usando comodines
- 12. ¿Buscar un archivo estático durante Application_BeginRequest?
- 13. xcode: buscar por archivo
- 14. Buscar la carpeta más reciente en un directorio en Python
- 15. La forma más eficiente de buscar las últimas x líneas de un archivo en python
- 16. leyendo un archivo en python
- 17. GZIP un archivo en Python
- 18. Buscar archivo de texto
- 19. Buscar todos los archivos CSV en un directorio usando Python
- 20. Buscar funciones definidas explícitamente en un módulo (python)
- 21. Cómo buscar un archivo .zip en IntelliJ (o .jar, etc.)
- 22. ¿Cómo buscar un archivo en la biblioteca java swing?
- 23. Buscar el propietario de un archivo en Unix
- 24. Buscar y reemplazar palabras/líneas en un archivo
- 25. Buscar en el repositorio SVN para un nombre de archivo
- 26. ¿Cómo buscar un archivo en el servidor de subversión?
- 27. Buscar un archivo con una cierta extensión en la carpeta
- 28. Buscar un archivo en el directorio con múltiples directorios
- 29. Buscar y obtener una línea en Python
- 30. Buscar cadena en archivo de texto C
Tenga en cuenta que estos ejemplos solo encontrarán archivos, no directorios con el mismo nombre. Si quiere encontrar ** cualquier objeto ** en el directorio con ese nombre, puede usar 'if name in file o name in dirs' –
Tenga cuidado con la distinción entre mayúsculas y minúsculas. 'para nombre en archivos:' fallará buscando 'super-photo.jpg' cuando es' super-photo.JPG' en el sistema de archivos. (una hora de mi vida me gustaría volver ;-) Una solución algo desordenada es 'if str.lower (name) en [x.lower() para x en archivos] ' –
¿Qué hay de usar ** yield ** en lugar de preparar la lista de resultados? ..... if fnmatch.fnmatch (nombre, patrón): yield os.path.join (root, name) – Berci