os.listdir()obtendrá todo lo que está en un directorio: archivos y directorios .
Si solo desea archivos, puede filtrar esto usando os.path:
from os import listdir
from os.path import isfile, join
onlyfiles =[f for f in listdir(mypath)if isfile(join(mypath, f))]
o se puede usar os.walk()lo que dió dos listas para cada directorio visitas it - división en archivos y directorios para usted. Si solo desea el directorio superior, puede romperlo la primera vez que produce
from os import walk
f =[]for(dirpath, dirnames, filenames)in walk(mypath):
f.extend(filenames)break
Un poco más simple: (_, _, filenames) = walk(mypath).next() (si está seguro de que la caminata devolverá al menos un valor, que debería).
misterbee
99
Ligera modificación para almacenar rutas completas: for (dirpath, dirnames, filenames) en os.walk (mypath): checksum_files.extend (os.path.join (dirpath, filename) para el nombre del archivo en los nombres de archivo) break
okigan
150
f.extend(filenames)en realidad no es equivalente a f = f + filenames. extendmodificará fen el lugar, mientras que agregar crea una nueva lista en una nueva ubicación de memoria. Esto significa extendque generalmente es más eficiente que +, pero a veces puede generar confusión si varios objetos contienen referencias a la lista. Por último, vale la pena señalar que f += filenameses equivalente a f.extend(filenames), nof = f + filenames .
Benjamin Hodgson
30
@misterbee, su solución es la mejor, solo una pequeña mejora:_, _, filenames = next(walk(mypath), (None, None, []))
bgusach
35
en uso de python 3.x(_, _, filenames) = next(os.walk(mypath))
ET-CS
1684
Prefiero usar el globmódulo, ya que coincide con el patrón y la expansión.
para aclarar, esto no devuelve el "camino completo"; simplemente devuelve la expansión del globo, sea lo que sea. Por ejemplo, dado /home/user/foo/bar/hello.txt, si se ejecuta en el directorio foo, glob("bar/*.txt")volverá bar/hello.txt. Hay casos en los que de hecho quiere la ruta completa (es decir, absoluta); para esos casos, consulte stackoverflow.com/questions/51520/…
¡¡¡¡hermoso!!!! entonces ... x=glob.glob("../train/*.png")me dará una variedad de mis rutas, siempre que sepa el nombre de la carpeta. ¡Muy guay!
Jennifer Crosby
860
Obtenga una lista de archivos con Python 2 y 3
os.listdir()
Cómo obtener todos los archivos (y directorios) en el directorio actual (Python 3)
A continuación, se incluyen métodos simples para recuperar solo archivos en el directorio actual, usando os y la listdir()función, en Python 3. Una exploración más profunda, demostrará cómo devolver carpetas en el directorio, pero no tendrá el archivo en el subdirectorio, para eso puede usar caminar - discutido más adelante).
import os
arr = os.listdir()print(arr)>>>['$RECYCLE.BIN','work.txt','3ebooks.txt','documents']
glob
Encontré a Glob más fácil seleccionar el archivo del mismo tipo o con algo en común. Mira el siguiente ejemplo:
import glob
txtfiles =[]for file in glob.glob("*.txt"):
txtfiles.append(file)
glob con lista de comprensión
import glob
mylist =[f for f in glob.glob("*.txt")]
glob con una función
La función devuelve una lista de la extensión dada (.txt, .docx ecc.) En el argumento
import glob
def filebrowser(ext=""):"Returns files with an extension"return[f for f in glob.glob(f"*{ext}")]
x = filebrowser(".txt")print(x)>>>['example.txt','fb.txt','intro.txt','help.txt']
glob extendiendo el código anterior
La función ahora devuelve una lista de archivos que coinciden con la cadena que pasa como argumento
import glob
def filesearch(word=""):"""Returns a list with all files with the word/extension in it"""
file =[]for f in glob.glob("*"):if word[0]==".":if f.endswith(word):
file.append(f)return file
elif word in f:
file.append(f)return file
return file
lookfor ="example",".py"for w in lookfor:print(f"{w:10} found => {filesearch(w)}")
salida
example found =>[].py found =>['search.py']
Obtener el nombre completo de la ruta con os.path.abspath
Como notó, no tiene la ruta completa del archivo en el código anterior. Si necesita tener la ruta absoluta, puede usar otra función del os.pathmódulo llamado _getfullpathname, colocando el archivo que obtiene os.listdir()como argumento. Hay otras formas de tener la ruta completa, como veremos más adelante (reemplacé, como lo sugiere mexmex, _getfullpathname con abspath).
import os
files_path =[os.path.abspath(x)for x in os.listdir()]print(files_path)>>>['F:\\documenti\applications.txt','F:\\documenti\collections.txt']
Obtenga el nombre de ruta completo de un tipo de archivo en todos los subdirectorios con walk
Encuentro esto muy útil para encontrar cosas en muchos directorios, y me ayudó a encontrar un archivo sobre el que no recordaba el nombre:
import os
# Getting the current work directory (cwd)
thisdir = os.getcwd()# r=root, d=directories, f = filesfor r, d, f in os.walk(thisdir):for file in f:if file.endswith(".docx"):print(os.path.join(r, file))
os.listdir(): obtener archivos en el directorio actual (Python 2)
En Python 2, si desea la lista de archivos en el directorio actual, debe dar el argumento como '.' o os.getcwd () en el método os.listdir.
import os
arr = os.listdir('.')print(arr)>>>['$RECYCLE.BIN','work.txt','3ebooks.txt','documents']
Para subir en el árbol de directorios
# Method 1
x = os.listdir('..')# Method 2
x= os.listdir('/')
Obtener archivos: os.listdir()en un directorio particular (Python 2 y 3)
import os
arr = os.listdir('F:\\python')print(arr)>>>['$RECYCLE.BIN','work.txt','3ebooks.txt','documents']
Obtenga archivos de un subdirectorio particular con os.listdir()
import os
x = os.listdir("./content")
os.walk('.') - directorio actual
import os
arr = next(os.walk('.'))[2]print(arr)>>>['5bs_Turismo1.pdf','5bs_Turismo1.pptx','esperienza.txt']
next(os.walk('.')) y os.path.join('dir', 'file')
import os
arr =[]for d,r,f in next(os.walk("F:\\_python")):for file in f:
arr.append(os.path.join(r,file))for f in arr:print(files)>>> F:\\_python\\dict_class.py
>>> F:\\_python\\programmi.txt
next(os.walk('F:\\') - Obtenga el camino completo - Lista de comprensión
[os.path.join(r,file)for r,d,f in next(os.walk("F:\\_python"))for file in f]>>>['F:\\_python\\dict_class.py','F:\\_python\\programmi.txt']
os.walk - Obtener ruta completa - todos los archivos en subdirectorios **
x =[os.path.join(r,file)for r,d,f in os.walk("F:\\_python")for file in f]print(x)>>>['F:\\_python\\dict.py','F:\\_python\\progr.txt','F:\\_python\\readl.py']
os.listdir() - obtener solo archivos txt
arr_txt =[x for x in os.listdir()if x.endswith(".txt")]print(arr_txt)>>>['work.txt','3ebooks.txt']
Utilizando globpara obtener la ruta completa de los archivos
Si necesito la ruta absoluta de los archivos:
from path import path
from glob import glob
x =[path(f).abspath()for f in glob("F:\\*.txt")]for f in x:print(f)>>> F:\acquistionline.txt
>>> F:\acquisti_2018.txt
>>> F:\bootstrap_jquery_ecc.txt
Utilizando os.path.isfilepara evitar directorios en la lista
import os.path
listOfFiles =[f for f in os.listdir()if os.path.isfile(f)]print(listOfFiles)>>>['a simple game.py','data.txt','decorator.py']
Utilizando pathlibdesde Python 3.4
import pathlib
flist =[]for p in pathlib.Path('.').iterdir():if p.is_file():print(p)
flist.append(p)>>> error.PNG
>>> exemaker.bat
>>> guiprova.mp3
>>> setup.py
>>> speak_gui2.py
>>> thumb.PNG
Con list comprehension:
flist =[p for p in pathlib.Path('.').iterdir()if p.is_file()]
Alternativamente, use en pathlib.Path()lugar depathlib.Path(".")
import os
x =[i[2]for i in os.walk('.')]
y=[]for t in x:for f in t:
y.append(f)print(y)>>>['append_to_list.py','data.txt','data1.txt','data2.txt','data_180617','os_walk.py','READ2.py','read_data.py','somma_defaltdic.py','substitute_words.py','sum_data.py','data.txt','data1.txt','data_180617']
Obtenga solo archivos con next y camine en un directorio
import os
x = next(os.walk('F://python'))[2]print(x)>>>['calculator.bat','calculator.py']
Obtenga solo directorios con next y camine en un directorio
import os
next(os.walk('F://python'))[1]# for the current dir use ('.')>>>['python3','others']
Obtenga todos los nombres de subdirectorios con walk
for r,d,f in os.walk("F:\\_python"):for dirs in d:print(dirs)>>>.vscode
>>> pyexcel
>>> pyschool.py
>>> subtitles
>>> _metaprogramming
>>>.ipynb_checkpoints
os.scandir() desde Python 3.5 y superior
import os
x =[f.name for f in os.scandir()if f.is_file()]print(x)>>>['calculator.bat','calculator.py']# Another example with scandir (a little variation from docs.python.org)# This one is more efficient than os.listdir.# In this case, it shows the files only in the current directory# where the script is executed.import os
with os.scandir()as i:for entry in i:if entry.is_file():print(entry.name)>>> ebookmaker.py
>>> error.PNG
>>> exemaker.bat
>>> guiprova.mp3
>>> setup.py
>>> speakgui4.py
>>> speak_gui2.py
>>> speak_gui3.py
>>> thumb.PNG
Ejemplos:
Ex. 1: ¿Cuántos archivos hay en los subdirectorios?
En este ejemplo, buscamos la cantidad de archivos que se incluyen en todo el directorio y sus subdirectorios.
import os
def count(dir, counter=0):"returns number of files in dir and subdirs"for pack in os.walk(dir):for f in pack[2]:
counter +=1return dir +" : "+ str(counter)+"files"print(count("F:\\python"))>>>'F:\\\python':12057 files'
Ej.2: ¿Cómo copiar todos los archivos de un directorio a otro?
Un script para ordenar en su computadora encontrar todos los archivos de un tipo (predeterminado: pptx) y copiarlos en una nueva carpeta.
import os
import shutil
from path import path
destination ="F:\\file_copied"# os.makedirs(destination)def copyfile(dir, filetype='pptx', counter=0):"Searches for pptx (or other - pptx is the default) files and copies them"for pack in os.walk(dir):for f in pack[2]:if f.endswith(filetype):
fullpath = pack[0]+"\\"+ f
print(fullpath)
shutil.copy(fullpath, destination)
counter +=1if counter >0:print('-'*30)print("\t==> Found in: `"+ dir +"` : "+ str(counter)+" files\n")for dir in os.listdir():"searches for folders that starts with `_`"if dir[0]=='_':# copyfile(dir, filetype='pdf')
copyfile(dir, filetype='txt')>>> _compiti18\Compito Contabilità1\conti.txt
>>> _compiti18\Compito Contabilità1\modula4.txt
>>> _compiti18\Compito Contabilità1\moduloa4.txt
>>>------------------------>>>==>Foundin:`_compiti18`:3 files
Ex. 3: Cómo obtener todos los archivos en un archivo txt
En caso de que desee crear un archivo txt con todos los nombres de archivo:
import os
mylist =""with open("filelist.txt","w", encoding="utf-8")as file:for eachfile in os.listdir():
mylist += eachfile +"\n"
file.write(mylist)
Ejemplo: txt con todos los archivos de un disco duro
"""
We are going to save a txt file with all the files in your directory.
We will use the function walk()
"""import os
# see all the methods of os# print(*dir(os), sep=", ")
listafile =[]
percorso =[]with open("lista_file.txt","w", encoding='utf-8')as testo:for root, dirs, files in os.walk("D:\\"):for file in files:
listafile.append(file)
percorso.append(root +"\\"+ file)
testo.write(file +"\n")
listafile.sort()print("N. of files", len(listafile))with open("lista_file_ordinata.txt","w", encoding="utf-8")as testo_ordinato:for file in listafile:
testo_ordinato.write(file +"\n")with open("percorso.txt","w", encoding="utf-8")as file_percorso:for file in percorso:
file_percorso.write(file +"\n")
os.system("lista_file.txt")
os.system("lista_file_ordinata.txt")
os.system("percorso.txt")
Todo el archivo de C: \ en un archivo de texto
Esta es una versión más corta del código anterior. Cambie la carpeta donde comenzar a buscar los archivos si necesita comenzar desde otra posición. Este código genera un archivo de texto de 50 mb en mi computadora con algo menos de 500,000 líneas con archivos con la ruta completa.
import os
with open("file.txt","w", encoding="utf-8")as filewrite:for r, d, f in os.walk("C:\\"):for file in f:
filewrite.write(f"{r + file}\n")
Cómo escribir un archivo con todas las rutas en una carpeta de un tipo
Con esta función, puede crear un archivo txt que tendrá el nombre de un tipo de archivo que busca (por ejemplo, pngfile.txt) con toda la ruta completa de todos los archivos de ese tipo. Puede ser útil a veces, creo.
import os
def searchfiles(extension='.ttf', folder='H:\\'):"Create a txt file with all the file of a type"with open(extension[1:]+"file.txt","w", encoding="utf-8")as filewrite:for r, d, f in os.walk(folder):for file in f:if file.endswith(extension):
filewrite.write(f"{r + file}\n")# looking for png file (fonts) in the hard disk H:\
searchfiles('.png','H:\\')>>> H:\4bs_18\Dolphins5.png
>>> H:\4bs_18\Dolphins6.png
>>> H:\4bs_18\Dolphins7.png
>>> H:\5_18\marketing html\assets\imageslogo2.png
>>> H:\7z001.png
>>> H:\7z002.png
(Nuevo) Encuentra todos los archivos y ábrelos con tkinter GUI
Solo quería agregar en este 2019 una pequeña aplicación para buscar todos los archivos en un directorio y poder abrirlos haciendo doble clic en el nombre del archivo en la lista.
import tkinter as tk
import os
def searchfiles(extension='.txt', folder='H:\\'):"insert all files in the listbox"for r, d, f in os.walk(folder):for file in f:if file.endswith(extension):
lb.insert(0, r +"\\"+ file)def open_file():
os.startfile(lb.get(lb.curselection()[0]))
root = tk.Tk()
root.geometry("400x400")
bt = tk.Button(root, text="Search", command=lambda:searchfiles('.png','H:\\'))
bt.pack()
lb = tk.Listbox(root)
lb.pack(fill="both", expand=1)
lb.bind("<Double-Button>",lambda x: open_file())
root.mainloop()
Esta es una mezcla de demasiadas respuestas a preguntas que no se hacen aquí. También puede valer la pena explicar cuáles son las advertencias o los enfoques recomendados. No estoy mejor si conozco una forma versus 20 formas de hacer lo mismo a menos que también sepa cuál es más apropiado usar cuándo.
cs95
Bien, lo antes posible echaré un vistazo a mi respuesta y trataré de hacerlo más limpio y con información más útil sobre la diferencia entre los métodos, etc.
Giovanni G. PY
No debe determinar la extensión del archivo verificando si el nombre del archivo contiene una subcadena. Eso puede causar muchos problemas. Recomiendo verificar siempre si el nombre de archivo termina con la subcadena particular.
ni1ight
Ok, @ n1light cambié el código ...
Giovanni G. PY
812
import os
os.listdir("somedirectory")
devolverá una lista de todos los archivos y directorios en "somedirectory".
Esto devuelve la ruta relativa de los archivos, en comparación con la ruta completa devuelto porglob.glob
xji
22
@JIXiang: os.listdir()siempre devuelve simples nombres de archivo (no rutas relativas). Lo que glob.glob()regresa es impulsado por el formato de ruta del patrón de entrada.
mklement0
os.listdir () -> Siempre enumera el directorio y el archivo dentro de la ubicación provista. ¿Hay alguna manera de enumerar solo el directorio, no los archivos?
RonyA
160
Una solución de una línea para obtener solo una lista de archivos (sin subdirectorios):
filenames = next(os.walk(path))[2]
o nombres de ruta absolutos:
paths =[os.path.join(path, fn)for fn in next(os.walk(path))[2]]
Solo una frase si ya lo has hecho import os. Parece menos conciso que glob()para mí.
ArtOfWarfare
44
problema con glob es que glob ('/ home / adam /*.*') devolvería una carpeta llamada 'something.something'
Remi
66
En OS X, hay algo llamado paquete. Es un directorio que generalmente debe tratarse como un archivo (como un .tar). ¿Desea que los traten como un archivo o un directorio? Usar glob()lo trataría como un archivo. Su método lo trataría como un directorio.
ArtOfWarfare
132
Obtener rutas de archivo completas de un directorio y todos sus subdirectorios
import os
def get_filepaths(directory):"""
This function will generate the file names in a directory
tree by walking the tree either top-down or bottom-up. For each
directory in the tree rooted at directory top (including top itself),
it yields a 3-tuple (dirpath, dirnames, filenames).
"""
file_paths =[]# List which will store all of the full filepaths.# Walk the tree.for root, directories, files in os.walk(directory):for filename in files:# Join the two strings in order to form the full filepath.
filepath = os.path.join(root, filename)
file_paths.append(filepath)# Add it to the list.return file_paths # Self-explanatory.# Run the above function and store its results in a variable.
full_file_paths = get_filepaths("/Users/johnny/Desktop/TEST")
La ruta que proporcioné en la función anterior contenía 3 archivos, dos de ellos en el directorio raíz y otro en una subcarpeta llamada "SUBFOLDER". Ahora puedes hacer cosas como:
>>>import pathlib
>>>[p for p in pathlib.Path('.').iterdir()if p.is_file()]
De acuerdo con PEP 428 , el objetivo de la pathlibbiblioteca es proporcionar una jerarquía simple de clases para manejar las rutas del sistema de archivos y las operaciones comunes que los usuarios realizan sobre ellas.
¡Gracias! Creo que es la única solución que no regresa directamente a list. Podría usar en p.namelugar del primero palternativamente si lo prefiere.
jeromej
1
¡Bienvenidos! Preferiría generar pathlib.Path()instancias ya que tienen muchos métodos útiles que no quisiera desperdiciar. También puede solicitarles str(p)nombres de ruta.
SzieberthAdam
66
Nota: La os.scandirsolución será más eficiente que os.listdircon un os.path.is_filecheque o similar, incluso si necesita un list(para que no se beneficie de la iteración diferida), porque os.scandirutiliza API proporcionadas por el sistema operativo que le brindan la is_fileinformación de forma gratuita a medida que itera , viaje sin vuelta por archivo en el disco a statellos en absoluto (en Windows, los DirEntrys conseguir que completa statinformación de forma gratuita, en sistemas * NIX que necesita statpara obtener información más allá is_file, is_dir, etc., pero DirEntrycachés en primera statpor conveniencia).
ShadowRanger
1
También puede usar entry.namepara obtener solo el nombre del archivo o entry.pathpara obtener su ruta completa. No más os.path.join () por todo el lugar.
user136036
56
Notas preliminares
Aunque hay una clara diferenciación entre archivo y directorio términos de en el texto de la pregunta, algunos pueden argumentar que los directorios son en realidad archivos especiales
La declaración: " todos los archivos de un directorio " se puede interpretar de dos maneras:
Todos los descendientes directos (o de nivel 1) solamente
Todos los descendientes en todo el árbol de directorios (incluidos los de los subdirectorios)
Cuando se hizo la pregunta, imagino que Python 2 era la versión LTS , sin embargo, Python 3 ( .5 ) ejecutará los ejemplos de código (los mantendré tan compatibles con Python 2 como sea posible; también, cualquier código perteneciente a Python que voy a publicar, es de v3.5.4 - a menos que se especifique lo contrario). Eso tiene consecuencias relacionadas con otra palabra clave en la pregunta: " agréguelas a una lista ":
En las versiones anteriores a Python 2.2 , las secuencias (iterables) se representaban principalmente mediante listas (tuplas, conjuntos, ...)
En Python 2.2 , se introdujo el concepto de generador ( [Python.Wiki]: Generadores ), cortesía de [Python 3]: La declaración de rendimiento ). A medida que pasaba el tiempo, las contrapartes generadoras comenzaron a aparecer para funciones que regresaban / funcionaban con listas
En Python 3 , el generador es el comportamiento predeterminado
No estoy seguro si devolver una lista sigue siendo obligatorio (o un generador también lo haría), pero pasar un generador al constructor de la lista creará una lista a partir de ella (y también la consumirá). El siguiente ejemplo ilustra las diferencias en [Python 3]: map ( function, iterable, ... )
>>>import sys
>>> sys.version
'2.7.10 (default, Mar 8 2016, 15:02:46) [MSC v.1600 64 bit (AMD64)]'>>> m = map(lambda x: x,[1,2,3])# Just a dummy lambda function>>> m, type(m)([1,2,3],<type 'list'>)>>> len(m)3
>>>import sys
>>> sys.version
'3.5.4 (v3.5.4:3f56838, Aug 8 2017, 02:17:05) [MSC v.1900 64 bit (AMD64)]'>>> m = map(lambda x: x,[1,2,3])>>> m, type(m)(<map object at 0x000001B4257342B0>,<class'map'>)>>> len(m)Traceback(most recent call last):File"<stdin>", line 1,in<module>TypeError: object of type 'map' has no len()>>> lm0 = list(m)# Build a list from the generator>>> lm0, type(lm0)([1,2,3],<class'list'>)>>>>>> lm1 = list(m)# Build a list from the same generator>>> lm1, type(lm1)# Empty list now - generator already consumed([],<class'list'>)
Los ejemplos se basarán en un directorio llamado root_dir con la siguiente estructura (este ejemplo es para Win , pero también estoy usando el mismo árbol en Lnx ):
Devuelve una lista que contiene los nombres de las entradas en el directorio dado por ruta. La lista está en orden arbitrario y no incluye las entradas especiales '.'y '..'...
>>>import os
>>> root_dir ="root_dir"# Path relative to current dir (os.getcwd())>>>>>> os.listdir(root_dir)# List all the items in root_dir['dir0','dir1','dir2','dir3','file0','file1']>>>>>>[item for item in os.listdir(root_dir)if os.path.isfile(os.path.join(root_dir, item))]# Filter items and only keep files (strip out directories)['file0','file1']
Un ejemplo más elaborado ( code_os_listdir.py ):
import os
from pprint import pformat
def _get_dir_content(path, include_folders, recursive):
entries = os.listdir(path)for entry in entries:
entry_with_path = os.path.join(path, entry)if os.path.isdir(entry_with_path):if include_folders:yield entry_with_path
if recursive:for sub_entry in _get_dir_content(entry_with_path, include_folders, recursive):yield sub_entry
else:yield entry_with_path
def get_dir_content(path, include_folders=True, recursive=True, prepend_folder_name=True):
path_len = len(path)+ len(os.path.sep)for item in _get_dir_content(path, include_folders, recursive):yield item if prepend_folder_name else item[path_len:]def _get_dir_content_old(path, include_folders, recursive):
entries = os.listdir(path)
ret = list()for entry in entries:
entry_with_path = os.path.join(path, entry)if os.path.isdir(entry_with_path):if include_folders:
ret.append(entry_with_path)if recursive:
ret.extend(_get_dir_content_old(entry_with_path, include_folders, recursive))else:
ret.append(entry_with_path)return ret
def get_dir_content_old(path, include_folders=True, recursive=True, prepend_folder_name=True):
path_len = len(path)+ len(os.path.sep)return[item if prepend_folder_name else item[path_len:]for item in _get_dir_content_old(path, include_folders, recursive)]def main():
root_dir ="root_dir"
ret0 = get_dir_content(root_dir, include_folders=True, recursive=True, prepend_folder_name=True)
lret0 = list(ret0)print(ret0, len(lret0), pformat(lret0))
ret1 = get_dir_content_old(root_dir, include_folders=False, recursive=True, prepend_folder_name=False)print(len(ret1), pformat(ret1))if __name__ =="__main__":
main()
Notas :
Hay dos implementaciones:
Uno que usa generadores (por supuesto, aquí parece inútil, ya que convierto inmediatamente el resultado en una lista)
El clásico (nombres de funciones que terminan en _old )
Se utiliza la recursividad (para entrar en subdirectorios)
Para cada implementación hay dos funciones:
Uno que comienza con un guión bajo ( _ ): "privado" (no debe llamarse directamente), eso hace todo el trabajo
El público (reiniciador sobre el anterior): simplemente elimina la ruta inicial (si es necesario) de las entradas devueltas. Es una implementación fea, pero es la única idea con la que podría venir en este momento
En términos de rendimiento, los generadores son generalmente un poco más rápidos (considerando tanto la creación como la iteración tiempos de ), pero no los probé en funciones recursivas, y también estoy iterando dentro de la función sobre los generadores internos: no sé cómo el rendimiento amigable es eso
Juega con los argumentos para obtener resultados diferentes.
Salida :
(py35x64_test) E:\Work\Dev\StackOverflow\q003207219>"e:\Work\Dev\VEnvs\py35x64_test\Scripts\python.exe""code_os_listdir.py"<generator object get_dir_content at 0x000001BDDBB3DF10>22['root_dir\\dir0','root_dir\\dir0\\dir00','root_dir\\dir0\\dir00\\dir000','root_dir\\dir0\\dir00\\dir000\\file0000','root_dir\\dir0\\dir00\\file000','root_dir\\dir0\\dir01','root_dir\\dir0\\dir01\\file010','root_dir\\dir0\\dir01\\file011','root_dir\\dir0\\dir02','root_dir\\dir0\\dir02\\dir020','root_dir\\dir0\\dir02\\dir020\\dir0200','root_dir\\dir1','root_dir\\dir1\\file10','root_dir\\dir1\\file11','root_dir\\dir1\\file12','root_dir\\dir2','root_dir\\dir2\\dir20','root_dir\\dir2\\dir20\\file200','root_dir\\dir2\\file20','root_dir\\dir3','root_dir\\file0','root_dir\\file1']11['dir0\\dir00\\dir000\\file0000','dir0\\dir00\\file000','dir0\\dir01\\file010','dir0\\dir01\\file011','dir1\\file10','dir1\\file11','dir1\\file12','dir2\\dir20\\file200','dir2\\file20','file0','file1']
Devuelve un iterador de objetos os.DirEntry correspondiente a las entradas en el directorio dado por la ruta . Las entradas se entregan en orden arbitrario, y las entradas especiales '.'y '..'no están incluidas.
El uso de scandir () en lugar de listdir () puede aumentar significativamente el rendimiento del código que también necesita información de tipo de archivo o atributo de archivo, porque los objetos os.DirEntry exponen esta información si el sistema operativo la proporciona al escanear un directorio. Todos los métodos os.DirEntry pueden realizar una llamada al sistema, pero is_dir () y is_file () generalmente solo requieren una llamada al sistema para enlaces simbólicos; os.DirEntry.stat () siempre requiere una llamada al sistema en Unix, pero solo requiere una para enlaces simbólicos en Windows.
>>>import os
>>> root_dir = os.path.join(".","root_dir")# Explicitly prepending current directory>>> root_dir
'.\\root_dir'>>>>>> scandir_iterator = os.scandir(root_dir)>>> scandir_iterator
<nt.ScandirIterator object at 0x00000268CF4BC140>>>>[item.path for item in scandir_iterator]['.\\root_dir\\dir0','.\\root_dir\\dir1','.\\root_dir\\dir2','.\\root_dir\\dir3','.\\root_dir\\file0','.\\root_dir\\file1']>>>>>>[item.path for item in scandir_iterator]# Will yield an empty list as it was consumed by previous iteration (automatically performed by the list comprehension)[]>>>>>> scandir_iterator = os.scandir(root_dir)# Reinitialize the generator>>>for item in scandir_iterator :...if os.path.isfile(item.path):...print(item.name)...
file0
file1
Notas :
Es similar a os.listdir
Pero también es más flexible (y ofrece más funcionalidad), más Python ic (y en algunos casos, más rápido)
Genere los nombres de archivo en un árbol de directorios recorriendo el árbol de arriba hacia abajo o de abajo hacia arriba. Para cada directorio en el árbol con raíz en directorio superior (incluyendo la parte superior en sí), se produce una 3-tupla ( dirpath, dirnames, filenames).
>>>import os
>>> root_dir = os.path.join(os.getcwd(),"root_dir")# Specify the full path>>> root_dir
'E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir'>>>>>> walk_generator = os.walk(root_dir)>>> root_dir_entry = next(walk_generator)# First entry corresponds to the root dir (passed as an argument)>>> root_dir_entry
('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir',['dir0','dir1','dir2','dir3'],['file0','file1'])>>>>>> root_dir_entry[1]+ root_dir_entry[2]# Display dirs and files (direct descendants) in a single list['dir0','dir1','dir2','dir3','file0','file1']>>>>>>[os.path.join(root_dir_entry[0], item)for item in root_dir_entry[1]+ root_dir_entry[2]]# Display all the entries in the previous list by their full path['E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0','E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir1','E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir2','E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir3','E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\file0','E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\file1']>>>>>>for entry in walk_generator:# Display the rest of the elements (corresponding to every subdir)...print(entry)...('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0',['dir00','dir01','dir02'],[])('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0\\dir00',['dir000'],['file000'])('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0\\dir00\\dir000',[],['file0000'])('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0\\dir01',[],['file010','file011'])('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0\\dir02',['dir020'],[])('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0\\dir02\\dir020',['dir0200'],[])('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0\\dir02\\dir020\\dir0200',[],[])('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir1',[],['file10','file11','file12'])('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir2',['dir20'],['file20'])('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir2\\dir20',[],['file200'])('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir3',[],[])
Notas :
Debajo de las escenas, usa os.scandir( os.listdiren versiones anteriores)
Devuelve una lista de nombres de ruta posiblemente vacía que coincida con el nombre de ruta , que debe ser una cadena que contenga una especificación de ruta. El nombre de ruta puede ser absoluto (como /usr/src/Python-1.5/Makefile) o relativo (como ../../Tools/*/*.gif), y puede contener comodines de estilo shell. Los enlaces simbólicos rotos se incluyen en los resultados (como en el shell). ... Cambiado en la versión 3.5 : Soporte para globos recursivos usando " **".
>>>import glob, os
>>> wildcard_pattern ="*">>> root_dir = os.path.join("root_dir", wildcard_pattern)# Match every file/dir name>>> root_dir
'root_dir\\*'>>>>>> glob_list = glob.glob(root_dir)>>> glob_list
['root_dir\\dir0','root_dir\\dir1','root_dir\\dir2','root_dir\\dir3','root_dir\\file0','root_dir\\file1']>>>>>>[item.replace("root_dir"+ os.path.sep,"")for item in glob_list]# Strip the dir name and the path separator from begining['dir0','dir1','dir2','dir3','file0','file1']>>>>>>for entry in glob.iglob(root_dir +"*", recursive=True):...print(entry)...
root_dir\
root_dir\dir0
root_dir\dir0\dir00
root_dir\dir0\dir00\dir000
root_dir\dir0\dir00\dir000\file0000
root_dir\dir0\dir00\file000
root_dir\dir0\dir01
root_dir\dir0\dir01\file010
root_dir\dir0\dir01\file011
root_dir\dir0\dir02
root_dir\dir0\dir02\dir020
root_dir\dir0\dir02\dir020\dir0200
root_dir\dir1
root_dir\dir1\file10
root_dir\dir1\file11
root_dir\dir1\file12
root_dir\dir2
root_dir\dir2\dir20
root_dir\dir2\dir20\file200
root_dir\dir2\file20
root_dir\dir3
root_dir\file0
root_dir\file1
Notas :
Usos os.listdir
Para árboles grandes (especialmente si el recursivo está activado ), se prefiere iglob
Permite el filtrado avanzado basado en el nombre (debido al comodín)
>>>import pathlib
>>> root_dir ="root_dir">>> root_dir_instance = pathlib.Path(root_dir)>>> root_dir_instance
WindowsPath('root_dir')>>> root_dir_instance.name
'root_dir'>>> root_dir_instance.is_dir()True>>>>>>[item.name for item in root_dir_instance.glob("*")]# Wildcard searching for all direct descendants['dir0','dir1','dir2','dir3','file0','file1']>>>>>>[os.path.join(item.parent.name, item.name)for item in root_dir_instance.glob("*")ifnot item.is_dir()]# Display paths (including parent) for files only['root_dir\\file0','root_dir\\file1']
def listdir(path):"""List directory contents, using cache."""try:
cached_mtime, list = cache[path]del cache[path]exceptKeyError:
cached_mtime, list =-1,[]
mtime = os.stat(path).st_mtime
if mtime != cached_mtime:
list = os.listdir(path)
list.sort()
cache[path]= mtime, list
return list
ctypes es una biblioteca de funciones foráneas para Python. Proporciona tipos de datos compatibles con C y permite funciones de llamada en archivos DLL o bibliotecas compartidas. Se puede usar para envolver estas bibliotecas en Python puro.
LinuxDirent64 es la representación de tipos de struct dirent64 de [man7]: dirent.h (0P) (también lo son las constantes DT_ ) de mi máquina: Ubtu 16 x64 ( 4.10.0-40-generic y libc6-dev: amd64 ). En otros sabores / versiones, la definición de estructura puede diferir, y si es así, el alias ctypes debe actualizarse, de lo contrario, generará un comportamiento indefinido
Devuelve datos en el os.walkformato de 's. No me molesté en hacerlo recursivo, pero a partir del código existente, sería una tarea bastante trivial.
Todo es factible en Win también, los datos (bibliotecas, funciones, estructuras, constantes, ...) difieren
Salida :
[cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow/q003207219]>./code_ctypes.py
3.5.2(default,Nov122018,13:43:14)[GCC 5.4.020160609] on linux
['root_dir',['dir2','dir1','dir3','dir0'],['file1','file0']]
Recupera una lista de nombres de archivos coincidentes, utilizando la API de Windows Unicode. Una interfaz para las funciones API FindFirstFileW / FindNextFileW / Find close.
>>>import os, win32file, win32con
>>> root_dir ="root_dir">>> wildcard ="*">>> root_dir_wildcard = os.path.join(root_dir, wildcard)>>> entry_list = win32file.FindFilesW(root_dir_wildcard)>>> len(entry_list)# Don't display the whole content as it's too long8>>>[entry[-2]for entry in entry_list]# Only display the entry names['.','..','dir0','dir1','dir2','dir3','file0','file1']>>>>>>[entry[-2]for entry in entry_list if entry[0]& win32con.FILE_ATTRIBUTE_DIRECTORY and entry[-2]notin(".","..")]# Filter entries and only display dir names (except self and parent)['dir0','dir1','dir2','dir3']>>>>>>[os.path.join(root_dir, entry[-2])for entry in entry_list if entry[0]&(win32con.FILE_ATTRIBUTE_NORMAL | win32con.FILE_ATTRIBUTE_ARCHIVE)]# Only display file "full" names['root_dir\\file0','root_dir\\file1']
El enlace de documentación es de ActiveState , ya que no encontré ninguna documentación oficial de PyWin32
Instale algún (otro) paquete de terceros que haga el truco
Lo más probable es que dependa de uno (o más) de los anteriores (tal vez con ligeras personalizaciones)
Notas :
El código debe ser portátil (excepto los lugares que se dirigen a un área específica, que están marcados) o cruzados:
plataforma ( Nix , Win ,)
Versión de Python (2, 3,)
Se utilizaron múltiples estilos de ruta (absoluto, parientes) en las variantes anteriores, para ilustrar el hecho de que las "herramientas" utilizadas son flexibles en esta dirección
_get_dir_content (desde el punto n . ° 1 ) puede implementarse utilizando cualquiera de estos enfoques (algunos requerirán más trabajo y otros menos)
Se podría hacer un filtrado avanzado (en lugar de solo archivo vs. dir): por ejemplo, el argumento include_folders podría reemplazarse por otro (por ejemplo, filter_func ), que sería una función que toma una ruta como argumento: filter_func=lambda x: True(esto no elimina cualquier cosa) y dentro de _get_dir_content algo como: if not filter_func(entry_with_path): continue(si la función falla para una entrada, se omitirá), pero cuanto más complejo se vuelva el código, más tardará en ejecutarse
Nota bene! Como se utiliza la recursividad, debo mencionar que hice algunas pruebas en mi computadora portátil ( Win 10 x64 ), totalmente ajenas a este problema, y cuando el nivel de recursión alcanzaba valores en algún lugar en el rango ( 990 .. 1000) ( límite de recursión - 1000 (predeterminado)), obtuve StackOverflow :). Si el árbol de directorios excede ese límite (no soy un experto en FS , así que no sé si eso es posible), eso podría ser un problema.
También debo mencionar que no intenté aumentar el límite de recursividad porque no tengo experiencia en el área (¿cuánto puedo aumentar antes de tener que aumentar también la pila en el sistema operativo?nivel), pero en teoría siempre habrá la posibilidad de falla, si la profundidad del directorio es mayor que el límite de recursión más alto posible (en esa máquina)
Los ejemplos de código son solo para fines demostrativos. Eso significa que no tomé en cuenta el manejo de errores (no creo que haya ningún bloque try / except / else / finally ), por lo que el código no es robusto (la razón es: para que sea lo más simple y breve posible ) Para la producción , también se debe agregar el manejo de errores
Otros enfoques:
Use Python solo como envoltorio
Todo se hace con otra tecnología.
Esa tecnología se invoca desde Python
El sabor más famoso que conozco es lo que llamo el enfoque de administrador del sistema :
Use Python (o cualquier lenguaje de programación) para ejecutar comandos de shell (y analizar sus salidas)
Algunos consideran que esto es un buen truco
Lo considero más como una solución poco convincente ( gainarie ), ya que la acción per se se realiza desde shell ( cmd en este caso) y, por lo tanto, no tiene nada que ver con Python .
El filtrado ( grep/ findstr) o el formato de salida se pueden hacer en ambos lados, pero no voy a insistir en ello. Además, lo usé deliberadamente en os.systemlugar de subprocess.Popen.
En general, se debe evitar este enfoque, ya que si algún formato de salida de comando difiere ligeramente entre las versiones / versiones del sistema operativo , el código de análisis también debe adaptarse; sin mencionar las diferencias entre locales).
Realmente me gustó la respuesta de adamk , sugiriendo que uses glob(), del módulo del mismo nombre. Esto le permite tener coincidencia de patrones con *s.
Pero como otras personas señalaron en los comentarios, glob()pueden tropezarse con direcciones de corte inconsistentes. Para ayudar con eso, le sugiero que use las funciones join()y expanduser()en el os.pathmódulo, y quizás también la getcwd()función en el osmódulo.
Como ejemplos:
from glob import glob
# Return everything under C:\Users\admin that contains a folder called wlp.
glob('C:\Users\admin\*\wlp')
Lo anterior es terrible: la ruta ha sido codificada y solo funcionará en Windows entre el nombre de la unidad y el \s que está codificado en la ruta.
from glob import glob
from os.path import join
# Return everything under Users, admin, that contains a folder called wlp.
glob(join('Users','admin','*','wlp'))
Lo anterior funciona mejor, pero se basa en el nombre de la carpeta Usersque a menudo se encuentra en Windows y no tan a menudo en otros sistemas operativos. También se basa en que el usuario tenga un nombre específico, admin.
from glob import glob
from os.path import expanduser, join
# Return everything under the user directory that contains a folder called wlp.
glob(join(expanduser('~'),'*','wlp'))
Esto funciona perfectamente en todas las plataformas.
Otro gran ejemplo que funciona perfectamente en todas las plataformas y hace algo un poco diferente:
from glob import glob
from os import getcwd
from os.path import join
# Return everything under the current directory that contains a folder called wlp.
glob(join(getcwd(),'*','wlp'))
Espero que estos ejemplos lo ayuden a ver el poder de algunas de las funciones que puede encontrar en los módulos estándar de la biblioteca Python.
def list_files(path):# returns a list of names (with extension, without full path) of all files # in folder path
files =[]for name in os.listdir(path):if os.path.isfile(os.path.join(path, name)):
files.append(name)return files
Para obtener mejores resultados, puede utilizar el listdir()método deos módulo junto con un generador (un generador es un iterador poderoso que mantiene su estado, ¿recuerda?). El siguiente código funciona bien con ambas versiones: Python 2 y Python 3.
Aquí hay un código:
import os
def files(path):for file in os.listdir(path):if os.path.isfile(os.path.join(path, file)):yield file
for file in files("."):print(file)
El listdir()método devuelve la lista de entradas para el directorio dado. El método os.path.isfile()devuelve Truesi la entrada dada es un archivo. Y el yieldoperador abandona la función pero mantiene su estado actual y solo devuelve el nombre de la entrada detectada como un archivo. Todo lo anterior nos permite recorrer la función del generador.
Nota: os.path.abspath(f)sería un sustituto algo más barato para os.path.join(os.getcwd(),f).
ShadowRanger
Sería más eficiente aún si usted empieza con cwd = os.path.abspath('.'), a continuación, utilizado cwden lugar de '.'y os.getcwd()a lo largo de las cargas de evitarse de llamadas al sistema redundantes.
Lo mismo se puede lograr solo en una línea con pathlib:filter(Path.is_file, Path().rglob('*'))
Georgy
9
Un maestro sabio me dijo una vez que:
Cuando hay varias formas establecidas de hacer algo, ninguna de ellas es buena para todos los casos.
Por lo tanto, agregaré una solución para un subconjunto del problema: con bastante frecuencia, solo queremos verificar si un archivo coincide con una cadena de inicio y una cadena de finalización, sin entrar en subdirectorios. Por lo tanto, nos gustaría una función que devuelva una lista de nombres de archivo, como:
Si quiere declarar primero dos funciones, puede hacerlo:
def file_filter(filename, radical='', extension=''):"Check if a filename matches a radical and extension"ifnot filename:returnFalse
filename = filename.strip()return(filename.startswith(radical)and filename.endswith(extension))def dir_filter(dirname='', radical='', extension=''):"Filter filenames in directory according to radical and extension"ifnot dirname:
dirname ='.'return[filename for filename in os.listdir(dirname)if file_filter(filename, radical, extension)]
Esta solución podría generalizarse fácilmente con expresiones regulares (y es posible que desee agregar un patternargumento, si no desea que sus patrones siempre se peguen al inicio o al final del nombre de archivo).
Otra variante muy legible para Python 3.4+ está usando pathlib.Path.glob:
from pathlib importPath
folder ='/foo'[f for f inPath(folder).glob('*')if f.is_file()]
Es simple hacer más específico, por ejemplo, solo busque archivos fuente de Python que no sean enlaces simbólicos, también en todos los subdirectorios:
[f for f inPath(folder).glob('**/*.py')ifnot f.is_symlink()]
Aquí está mi función de propósito general para esto. Devuelve una lista de rutas de archivos en lugar de nombres de archivos, ya que me pareció más útil. Tiene algunos argumentos opcionales que lo hacen versátil. Por ejemplo, a menudo lo uso con argumentos como pattern='*.txt'o subfolders=True.
import os
import fnmatch
def list_paths(folder='.', pattern='*', case_sensitive=False, subfolders=False):"""Return a list of the file paths matching the pattern in the specified
folder, optionally including files inside subfolders.
"""
match = fnmatch.fnmatchcase if case_sensitive else fnmatch.fnmatch
walked = os.walk(folder)if subfolders else[next(os.walk(folder))]return[os.path.join(root, f)for root, dirnames, filenames in walked
for f in filenames if match(f, pattern)]
Proporcionaré un ejemplo de una línea donde se puede proporcionar la ruta de origen y el tipo de archivo como entrada. El código devuelve una lista de nombres de archivo con extensión csv. Uso . en caso de que sea necesario devolver todos los archivos. Esto también explorará recursivamente los subdirectorios.
[y for x in os.walk(sourcePath) for y in glob(os.path.join(x[0], '*.csv'))]
Modifique las extensiones de archivo y la ruta de origen según sea necesario.
Si vas a usar glob, entonces solo usa glob('**/*.csv', recursive=True). No es necesario combinar esto con os.walk()recurse ( recursivey **son compatibles desde Python 3.5).
Respuestas:
os.listdir()
obtendrá todo lo que está en un directorio: archivos y directorios .Si solo desea archivos, puede filtrar esto usando
os.path
:o se puede usar
os.walk()
lo que dió dos listas para cada directorio visitas it - división en archivos y directorios para usted. Si solo desea el directorio superior, puede romperlo la primera vez que producefuente
(_, _, filenames) = walk(mypath).next()
(si está seguro de que la caminata devolverá al menos un valor, que debería).f.extend(filenames)
en realidad no es equivalente af = f + filenames
.extend
modificaráf
en el lugar, mientras que agregar crea una nueva lista en una nueva ubicación de memoria. Esto significaextend
que generalmente es más eficiente que+
, pero a veces puede generar confusión si varios objetos contienen referencias a la lista. Por último, vale la pena señalar quef += filenames
es equivalente af.extend(filenames)
, nof = f + filenames
._, _, filenames = next(walk(mypath), (None, None, []))
(_, _, filenames) = next(os.walk(mypath))
Prefiero usar el
glob
módulo, ya que coincide con el patrón y la expansión.Devolverá una lista con los archivos consultados:
fuente
/home/user/foo/bar/hello.txt
, si se ejecuta en el directoriofoo
,glob("bar/*.txt")
volverábar/hello.txt
. Hay casos en los que de hecho quiere la ruta completa (es decir, absoluta); para esos casos, consulte stackoverflow.com/questions/51520/…glob.glob("*")
haría.x=glob.glob("../train/*.png")
me dará una variedad de mis rutas, siempre que sepa el nombre de la carpeta. ¡Muy guay!Cómo obtener todos los archivos (y directorios) en el directorio actual (Python 3)
A continuación, se incluyen métodos simples para recuperar solo archivos en el directorio actual, usando
os
y lalistdir()
función, en Python 3. Una exploración más profunda, demostrará cómo devolver carpetas en el directorio, pero no tendrá el archivo en el subdirectorio, para eso puede usar caminar - discutido más adelante).Encontré a Glob más fácil seleccionar el archivo del mismo tipo o con algo en común. Mira el siguiente ejemplo:
La función devuelve una lista de la extensión dada (.txt, .docx ecc.) En el argumento
La función ahora devuelve una lista de archivos que coinciden con la cadena que pasa como argumento
salida
Como notó, no tiene la ruta completa del archivo en el código anterior. Si necesita tener la ruta absoluta, puede usar otra función del
os.path
módulo llamado_getfullpathname
, colocando el archivo que obtieneos.listdir()
como argumento. Hay otras formas de tener la ruta completa, como veremos más adelante (reemplacé, como lo sugiere mexmex, _getfullpathname conabspath
).Encuentro esto muy útil para encontrar cosas en muchos directorios, y me ayudó a encontrar un archivo sobre el que no recordaba el nombre:
En Python 2, si desea la lista de archivos en el directorio actual, debe dar el argumento como '.' o os.getcwd () en el método os.listdir.
Si necesito la ruta absoluta de los archivos:
Con
list comprehension
:Alternativamente, use en
pathlib.Path()
lugar depathlib.Path(".")
En este ejemplo, buscamos la cantidad de archivos que se incluyen en todo el directorio y sus subdirectorios.
Un script para ordenar en su computadora encontrar todos los archivos de un tipo (predeterminado: pptx) y copiarlos en una nueva carpeta.
En caso de que desee crear un archivo txt con todos los nombres de archivo:
Con esta función, puede crear un archivo txt que tendrá el nombre de un tipo de archivo que busca (por ejemplo, pngfile.txt) con toda la ruta completa de todos los archivos de ese tipo. Puede ser útil a veces, creo.
fuente
devolverá una lista de todos los archivos y directorios en "somedirectory".
fuente
glob.glob
os.listdir()
siempre devuelve simples nombres de archivo (no rutas relativas). Lo queglob.glob()
regresa es impulsado por el formato de ruta del patrón de entrada.Una solución de una línea para obtener solo una lista de archivos (sin subdirectorios):
o nombres de ruta absolutos:
fuente
import os
. Parece menos conciso queglob()
para mí.glob()
lo trataría como un archivo. Su método lo trataría como un directorio.Obtener rutas de archivo completas de un directorio y todos sus subdirectorios
print full_file_paths
que imprimirá la lista:['/Users/johnny/Desktop/TEST/file1.txt', '/Users/johnny/Desktop/TEST/file2.txt', '/Users/johnny/Desktop/TEST/SUBFOLDER/file3.dat']
Si lo desea, puede abrir y leer el contenido, o enfocarse solo en archivos con la extensión ".dat" como en el siguiente código:
/Users/johnny/Desktop/TEST/SUBFOLDER/file3.dat
fuente
Desde la versión 3.4 hay iteradores incorporados para esto que son mucho más eficientes que
os.listdir()
:pathlib
: Nuevo en la versión 3.4.De acuerdo con PEP 428 , el objetivo de la
pathlib
biblioteca es proporcionar una jerarquía simple de clases para manejar las rutas del sistema de archivos y las operaciones comunes que los usuarios realizan sobre ellas.os.scandir()
: Nuevo en la versión 3.5.Tenga en cuenta que
os.walk()
utiliza enos.scandir()
lugar de laos.listdir()
versión 3.5, y su velocidad se incrementó en 2-20 veces según PEP 471 .Permítanme recomendar también leer el comentario de ShadowRanger a continuación.
fuente
list
. Podría usar enp.name
lugar del primerop
alternativamente si lo prefiere.pathlib.Path()
instancias ya que tienen muchos métodos útiles que no quisiera desperdiciar. También puede solicitarlesstr(p)
nombres de ruta.os.scandir
solución será más eficiente queos.listdir
con unos.path.is_file
cheque o similar, incluso si necesita unlist
(para que no se beneficie de la iteración diferida), porqueos.scandir
utiliza API proporcionadas por el sistema operativo que le brindan lais_file
información de forma gratuita a medida que itera , viaje sin vuelta por archivo en el disco astat
ellos en absoluto (en Windows, losDirEntry
s conseguir que completastat
información de forma gratuita, en sistemas * NIX que necesitastat
para obtener información más alláis_file
,is_dir
, etc., peroDirEntry
cachés en primerastat
por conveniencia).entry.name
para obtener solo el nombre del archivo oentry.path
para obtener su ruta completa. No más os.path.join () por todo el lugar.Notas preliminares
Cuando se hizo la pregunta, imagino que Python 2 era la versión LTS , sin embargo, Python 3 ( .5 ) ejecutará los ejemplos de código (los mantendré tan compatibles con Python 2 como sea posible; también, cualquier código perteneciente a Python que voy a publicar, es de v3.5.4 - a menos que se especifique lo contrario). Eso tiene consecuencias relacionadas con otra palabra clave en la pregunta: " agréguelas a una lista ":
Los ejemplos se basarán en un directorio llamado root_dir con la siguiente estructura (este ejemplo es para Win , pero también estoy usando el mismo árbol en Lnx ):
Soluciones
Enfoques programáticos:
[Python 3]: os. listdir ( ruta = '.' )
Un ejemplo más elaborado ( code_os_listdir.py ):
Notas :
Salida :
[Python 3]: os. scandir ( ruta = '.' ) ( Python 3.5 +, backport: [PyPI]: scandir )
Notas :
os.listdir
[Python 3]: os. caminar ( top, topdown = True, onerror = None, followlinks = False )
Notas :
os.scandir
(os.listdir
en versiones anteriores)[Python 3]: glob. glob ( pathname, *, recursive = False ) ( [Python 3]: glob. iglob ( pathname, *, recursive = False ) )
Notas :
os.listdir
[Python 3]: clase pathlib. Path ( * pathsegments ) ( Python 3.4 +, backport: [PyPI]: pathlib2 )
Notas :
[Python 2]: dircache.listdir (ruta) ( solo Python 2 )
os.listdir
con almacenamiento en caché[man7]: OPENDIR (3) / [man7]: READDIR (3) / [man7]: CLOSEDIR (3) a través de [Python 3]: ctypes - Una biblioteca de funciones foráneas para Python ( POSIX específico)
code_ctypes.py :
Notas :
os.walk
formato de 's. No me molesté en hacerlo recursivo, pero a partir del código existente, sería una tarea bastante trivial.Salida :
[ActiveState.Docs]: win32file.FindFilesW ( Win específico)
Notas :
win32file.FindFilesW
es parte de [GitHub]: mhammond / pywin32 - Extensiones de Python para Windows (pywin32) , que es un contenedor de Python sobre WINAPI sNotas :
El código debe ser portátil (excepto los lugares que se dirigen a un área específica, que están marcados) o cruzados:
Se utilizaron múltiples estilos de ruta (absoluto, parientes) en las variantes anteriores, para ilustrar el hecho de que las "herramientas" utilizadas son flexibles en esta dirección
os.listdir
yos.scandir
use opendir / readdir / closedir ( [MS.Docs]: FindFirstFileW function / [MS.Docs]: FindNextFileW function / [MS.Docs]: FindClose function ) (via [GitHub]: python / cpython - (master) cpython / Módulos / posixmodule.c )win32file.FindFilesW
usa esas funciones ( específicas de Win ) también (a través de [GitHub]: mhammond / pywin32 - (master) pywin32 / win32 / src / win32file.i )_get_dir_content (desde el punto n . ° 1 ) puede implementarse utilizando cualquiera de estos enfoques (algunos requerirán más trabajo y otros menos)
filter_func=lambda x: True
(esto no elimina cualquier cosa) y dentro de _get_dir_content algo como:if not filter_func(entry_with_path): continue
(si la función falla para una entrada, se omitirá), pero cuanto más complejo se vuelva el código, más tardará en ejecutarseNota bene! Como se utiliza la recursividad, debo mencionar que hice algunas pruebas en mi computadora portátil ( Win 10 x64 ), totalmente ajenas a este problema, y cuando el nivel de recursión alcanzaba valores en algún lugar en el rango ( 990 .. 1000) ( límite de recursión - 1000 (predeterminado)), obtuve StackOverflow :). Si el árbol de directorios excede ese límite (no soy un experto en FS , así que no sé si eso es posible), eso podría ser un problema.
También debo mencionar que no intenté aumentar el límite de recursividad porque no tengo experiencia en el área (¿cuánto puedo aumentar antes de tener que aumentar también la pila en el sistema operativo?nivel), pero en teoría siempre habrá la posibilidad de falla, si la profundidad del directorio es mayor que el límite de recursión más alto posible (en esa máquina)
Los ejemplos de código son solo para fines demostrativos. Eso significa que no tomé en cuenta el manejo de errores (no creo que haya ningún bloque try / except / else / finally ), por lo que el código no es robusto (la razón es: para que sea lo más simple y breve posible ) Para la producción , también se debe agregar el manejo de errores
Otros enfoques:
Use Python solo como envoltorio
El sabor más famoso que conozco es lo que llamo el enfoque de administrador del sistema :
grep
/findstr
) o el formato de salida se pueden hacer en ambos lados, pero no voy a insistir en ello. Además, lo usé deliberadamente enos.system
lugar desubprocess.Popen
.En general, se debe evitar este enfoque, ya que si algún formato de salida de comando difiere ligeramente entre las versiones / versiones del sistema operativo , el código de análisis también debe adaptarse; sin mencionar las diferencias entre locales).
fuente
Realmente me gustó la respuesta de adamk , sugiriendo que uses
glob()
, del módulo del mismo nombre. Esto le permite tener coincidencia de patrones con*
s.Pero como otras personas señalaron en los comentarios,
glob()
pueden tropezarse con direcciones de corte inconsistentes. Para ayudar con eso, le sugiero que use las funcionesjoin()
yexpanduser()
en elos.path
módulo, y quizás también lagetcwd()
función en elos
módulo.Como ejemplos:
Lo anterior es terrible: la ruta ha sido codificada y solo funcionará en Windows entre el nombre de la unidad y el
\
s que está codificado en la ruta.Lo anterior funciona mejor, pero se basa en el nombre de la carpeta
Users
que a menudo se encuentra en Windows y no tan a menudo en otros sistemas operativos. También se basa en que el usuario tenga un nombre específico,admin
.Esto funciona perfectamente en todas las plataformas.
Otro gran ejemplo que funciona perfectamente en todas las plataformas y hace algo un poco diferente:
Espero que estos ejemplos lo ayuden a ver el poder de algunas de las funciones que puede encontrar en los módulos estándar de la biblioteca Python.
fuente
**
funciona siempre que lo establezcarecursive = True
. Vea los documentos aquí: docs.python.org/3.5/library/glob.html#glob.globfuente
Si está buscando una implementación Python de find , esta es una receta que uso con bastante frecuencia:
Así que hice un paquete PyPI y también hay un repositorio GitHub . Espero que alguien lo encuentre potencialmente útil para este código.
fuente
Para obtener mejores resultados, puede utilizar el
listdir()
método deos
módulo junto con un generador (un generador es un iterador poderoso que mantiene su estado, ¿recuerda?). El siguiente código funciona bien con ambas versiones: Python 2 y Python 3.Aquí hay un código:
El
listdir()
método devuelve la lista de entradas para el directorio dado. El métodoos.path.isfile()
devuelveTrue
si la entrada dada es un archivo. Y elyield
operador abandona la función pero mantiene su estado actual y solo devuelve el nombre de la entrada detectada como un archivo. Todo lo anterior nos permite recorrer la función del generador.fuente
Al devolver una lista de rutas de archivos absolutas, no se repite en subdirectorios
fuente
os.path.abspath(f)
sería un sustituto algo más barato paraos.path.join(os.getcwd(),f)
.cwd = os.path.abspath('.')
, a continuación, utilizadocwd
en lugar de'.'
yos.getcwd()
a lo largo de las cargas de evitarse de llamadas al sistema redundantes.Aquí uso una estructura recursiva.
fuente
pathlib
:filter(Path.is_file, Path().rglob('*'))
Un maestro sabio me dijo una vez que:
Por lo tanto, agregaré una solución para un subconjunto del problema: con bastante frecuencia, solo queremos verificar si un archivo coincide con una cadena de inicio y una cadena de finalización, sin entrar en subdirectorios. Por lo tanto, nos gustaría una función que devuelva una lista de nombres de archivo, como:
Si quiere declarar primero dos funciones, puede hacerlo:
Esta solución podría generalizarse fácilmente con expresiones regulares (y es posible que desee agregar un
pattern
argumento, si no desea que sus patrones siempre se peguen al inicio o al final del nombre de archivo).fuente
Usando generadores
fuente
Otra variante muy legible para Python 3.4+ está usando pathlib.Path.glob:
Es simple hacer más específico, por ejemplo, solo busque archivos fuente de Python que no sean enlaces simbólicos, también en todos los subdirectorios:
fuente
Aquí está mi función de propósito general para esto. Devuelve una lista de rutas de archivos en lugar de nombres de archivos, ya que me pareció más útil. Tiene algunos argumentos opcionales que lo hacen versátil. Por ejemplo, a menudo lo uso con argumentos como
pattern='*.txt'
osubfolders=True
.fuente
Proporcionaré un ejemplo de una línea donde se puede proporcionar la ruta de origen y el tipo de archivo como entrada. El código devuelve una lista de nombres de archivo con extensión csv. Uso . en caso de que sea necesario devolver todos los archivos. Esto también explorará recursivamente los subdirectorios.
[y for x in os.walk(sourcePath) for y in glob(os.path.join(x[0], '*.csv'))]
Modifique las extensiones de archivo y la ruta de origen según sea necesario.
fuente
glob
, entonces solo usaglob('**/*.csv', recursive=True)
. No es necesario combinar esto conos.walk()
recurse (recursive
y**
son compatibles desde Python 3.5).Para python2: pip install rglob
fuente
dircache es "Desaprobado desde la versión 2.6: el módulo dircache se ha eliminado en Python 3.0".
fuente