¿Cómo puedo enumerar todos los archivos de un directorio en Python y agregarlos a un archivo list?

respuesta

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 puede usar os.walk()lo que generará dos listas para cada directorio que visite, dividiéndose en archivos y directorios para usted. Si solo desea el directorio superior, puede romper la primera vez que cede

from os import walk

f = []
for (dirpath, dirnames, filenames) in walk(mypath):
    f.extend(filenames)
    break

o, más corto:

from os import walk

filenames = next(walk(mypath), (None, None, []))[2]  # [] if no file

Prefiero usar el globmódulo, ya que hace coincidencia de patrones y expansión.

import glob
print(glob.glob("/home/adam/*"))

Hace coincidencia de patrones de forma intuitiva

import glob
# All files and directories ending with .txt and that don't begin with a dot:
print(glob.glob("/home/adam/*.txt")) 
# All files and directories ending with .txt with depth of 2 folders, ignoring names beginning with a dot:
print(glob.glob("/home/adam/*/*.txt")) 

Devolverá una lista con los archivos y directorios consultados:

['/home/adam/file1.txt', '/home/adam/file2.txt', .... ]

Tenga en cuenta que globignora .los archivos y directorios que comienzan con un punto, ya que se consideran archivos y directorios ocultos, a menos que el patrón sea algo así como .*.

Úselo glob.escapepara escapar de cadenas que no están destinadas a ser patrones:

print(glob.glob(glob.escape(directory_name) + "/*.txt"))

lista en el directorio actual

Con listdir en el módulo os, obtiene los archivos y las carpetas en el directorio actual

 import os

 arr = os.listdir()

Buscando en un directorio

arr = os.listdir('c:\\files')

con glob puede especificar un tipo de archivo para listar como este

import glob

txtfiles = []
for file in glob.glob("*.txt"):
    txtfiles.append(file)

o

mylist = [f for f in glob.glob("*.txt")]

obtener la ruta completa de solo los archivos en el directorio actual

import os
from os import listdir
from os.path import isfile, join

cwd = os.getcwd()
onlyfiles = [os.path.join(cwd, f) for f in os.listdir(cwd) if 
os.path.isfile(os.path.join(cwd, f))]
print(onlyfiles) 

['G:\\getfilesname\\getfilesname.py', 'G:\\getfilesname\\example.txt']

Obtener el nombre completo de la ruta conos.path.abspath

Obtienes la ruta completa a cambio

 import os
 files_path = [os.path.abspath(x) for x in os.listdir()]
 print(files_path)
 
 ['F:\\documenti\applications.txt', 'F:\\documenti\collections.txt']

Caminar: recorrer subdirectorios

os.walk devuelve la raíz, la lista de directorios y la lista de archivos, por eso los descomprimí en r, d, f en el bucle for; luego busca otros archivos y directorios en las subcarpetas de la raíz y así sucesivamente hasta que no haya subcarpetas.

import os

# Getting the current work directory (cwd)
thisdir = os.getcwd()

# r=root, d=directories, f = files
for r, d, f in os.walk(thisdir):
    for file in f:
        if file.endswith(".docx"):
            print(os.path.join(r, file))

Para subir en el árbol de directorios

# Method 1
x = os.listdir('..')

# Method 2
x= os.listdir('/')

Obtener archivos de un subdirectorio particular conos.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

siguiente... caminar

 [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

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")]
 

Usando globpara obtener la ruta completa de los archivos

from path import path
from glob import glob

x = [path(f).abspath() for f in glob("F:\\*.txt")]

Uso os.path.isfilepara evitar directorios en la lista

import os.path
listOfFiles = [f for f in os.listdir() if os.path.isfile(f)]

Usando pathlibdesde Python 3.4

import pathlib

flist = []
for p in pathlib.Path('.').iterdir():
    if p.is_file():
        print(p)
        flist.append(p)

con list comprehension:

flist = [p for p in pathlib.Path('.').iterdir() if p.is_file()]

Use el método glob en pathlib.Path()

import pathlib

py = pathlib.Path().glob("*.py")

Obtenga todos y solo los archivos con os.walk: verifica solo el tercer elemento devuelto, es decir, la lista de archivos

import os
x = [i[2] for i in os.walk('.')]
y=[]
for t in x:
    for f in t:
        y.append(f)

Obtener solo archivos con el siguiente en un directorio: devuelve solo el archivo en la carpeta raíz

 import os
 x = next(os.walk('F://python'))[2]

Obtenga solo directorios con next y camine en un directorio, porque en el elemento [1] solo están las carpetas

 import os
 next(os.walk('F://python'))[1] # for the current dir use ('.')
 
 >>> ['python3','others']

Obtener todos los nombres de subdirección conwalk

for r,d,f in os.walk("F:\\_python"):
    for dirs in d:
        print(dirs)

os.scandir()desde Python 3.5 y superior

import os
x = [f.name for f in os.scandir() if f.is_file()]

# 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)
import os
os.listdir("somedirectory")

devolverá una lista de todos los archivos y directorios en "somedirectory".

Una solución de una línea para obtener solo una lista de archivos (sin subdirectorios):

filenames = next(os.walk(path))[2]

o rutas absolutas:

paths = [os.path.join(path, fn) for fn in next(os.walk(path))[2]]

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 "SUCARPETA". Ahora puedes hacer cosas como:
  • print full_file_pathsque 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 código a continuación:

for f in full_file_paths:
  if f.endswith(".dat"):
    print f

/Users/johnny/Desktop/TEST/SUBFOLDER/file3.dat

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.

>>> 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.

os.scandir(): Nuevo en la versión 3.5.

>>> import os
>>> [entry for entry in os.scandir('.') if entry.is_file()]

Tenga en cuenta que os.walk()usa os.scandir()en lugar de os.listdir()desde la versión 3.5, y su velocidad aumentó de 2 a 20 veces según PEP 471 .

Permítanme también recomendar leer el comentario de ShadowRanger a continuación.

notas preliminares

  • Aunque hay una clara diferenciación entre los términos de archivo y directorio 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:
    1. Solo todos los descendientes directos (o de nivel 1)
    2. Todos los descendientes en todo el árbol de directorios (incluidos los de los subdirectorios)
  • Cuando se hizo la pregunta, me imagino que Python 2 era la versión LTS , sin embargo, Python 3 ( .5 ) ejecutará los ejemplos de código (los mantendré lo más compatibles posible con Python 2 ; también, cualquier código que pertenezca 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: " agregarlos 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 ). Con el paso del tiempo, comenzaron a aparecer contrapartes generadoras para funciones que regresaban/trabajaban con listas
    • En Python 3 , el generador es el comportamiento predeterminado
    • No estoy seguro de 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]: mapa ( función, 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 ):

    E:\Work\Dev\StackOverflow\q003207219>tree /f "root_dir"
    Folder PATH listing for volume Work
    Volume serial number is 00000029 3655:6FED
    E:\WORK\DEV\STACKOVERFLOW\Q003207219\ROOT_DIR
    ¦   file0
    ¦   file1
    ¦
    +---dir0
    ¦   +---dir00
    ¦   ¦   ¦   file000
    ¦   ¦   ¦
    ¦   ¦   +---dir000
    ¦   ¦           file0000
    ¦   ¦
    ¦   +---dir01
    ¦   ¦       file010
    ¦   ¦       file011
    ¦   ¦
    ¦   +---dir02
    ¦       +---dir020
    ¦           +---dir0200
    +---dir1
    ¦       file10
    ¦       file11
    ¦       file12
    ¦
    +---dir2
    ¦   ¦   file20
    ¦   ¦
    ¦   +---dir20
    ¦           file200
    ¦
    +---dir3
    


Soluciones

Enfoques programáticos:

  1. [Python 3]: OS. listdir ( ruta = '.' )

    Return a list containing the names of the entries in the directory given by path. The list is in arbitrary order, and does not include the special entries '.' and '..' ...


    >>> 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 inmediatamente convierto el resultado en una lista)
      • El clásico (nombres de funciones que terminan en _old )
    • Se utiliza 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 (envoltura 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 que se me ocurre en este momento.
    • En términos de rendimiento, los generadores son generalmente un poco más rápidos (considerando los tiempos de creación e iteración ), pero no los probé en funciones recursivas, y también estoy iterando dentro de la función sobre generadores internos; no sé cómo funciona el rendimiento. amistoso es eso
    • Juega con los argumentos para obtener diferentes resultados


    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']
    


  1. [Python 3]: OS. scandir ( ruta = '.' ) ( Python 3.5 +, backport: [PyPI]: scandir )

    Return an iterator of os.DirEntry objects corresponding to the entries in the directory given by path. The entries are yielded in arbitrary order, and the special entries '.' and '..' are not included.

    Using scandir() instead of listdir() can significantly increase the performance of code that also needs file type or file attribute information, because os.DirEntry objects expose this information if the operating system provides it when scanning a directory. All os.DirEntry methods may perform a system call, but is_dir() and is_file() usually only require a system call for symbolic links; os.DirEntry.stat() always requires a system call on Unix but only requires one for symbolic links on 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 aos.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)


  1. [Python 3]: OS. caminar ( arriba, arriba abajo = Verdadero, onerror = Ninguno, seguir enlaces = Falso )

    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).


    >>> 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)
    • Hace el trabajo pesado recurriendo en subcarpetas


  1. [Python 3]: global. glob ( ruta, *, recursivo=Falso ) ( [Python 3]: glob. iglob ( ruta, *, recursivo=Falso ) )

    Return a possibly-empty list of path names that match pathname, which must be a string containing a path specification. pathname can be either absolute (like /usr/src/Python-1.5/Makefile) or relative (like ../../Tools/*/*.gif), and can contain shell-style wildcards. Broken symlinks are included in the results (as in the shell).
    ...
    Changed in version 3.5: Support for recursive globs using “**”.


    >>> 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 :

    • Usosos.listdir
    • Para árboles grandes (especialmente si el recurso recursivo está activado), se prefiere iglob
    • Permite el filtrado avanzado basado en el nombre (debido al comodín)


  1. [Python 3]: clase pathlib. Ruta ( *pathsegments ) ( Python 3.4 +, backport: [PyPI]: pathlib2 )

    >>> 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("*") if not item.is_dir()]  # Display paths (including parent) for files only
    ['root_dir\\file0', 'root_dir\\file1']
    

    Notas :

    • Esta es una forma de lograr nuestro objetivo.
    • Es el estilo OOP de manejar rutas
    • Ofrece muchas funcionalidades


  1. [Python 2]: dircache.listdir(ruta) ( solo Python 2 )


    def listdir(path):
        """List directory contents, using cache."""
        try:
            cached_mtime, list = cache[path]
            del cache[path]
        except KeyError:
            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
    


  1. [man7]: OPENDIR(3) / [man7]: READDIR(3) / [man7]: CLOSEDIR(3) a través de [Python 3]: ctypes - Una biblioteca de funciones externas para Python ( específica de POSIX )

    ctypes is a foreign function library for Python. It provides C compatible data types, and allows calling functions in DLLs or shared libraries. It can be used to wrap these libraries in pure Python.

    code_ctypes.py :

    #!/usr/bin/env python3
    
    import sys
    from ctypes import Structure, \
        c_ulonglong, c_longlong, c_ushort, c_ubyte, c_char, c_int, \
        CDLL, POINTER, \
        create_string_buffer, get_errno, set_errno, cast
    
    
    DT_DIR = 4
    DT_REG = 8
    
    char256 = c_char * 256
    
    
    class LinuxDirent64(Structure):
        _fields_ = [
            ("d_ino", c_ulonglong),
            ("d_off", c_longlong),
            ("d_reclen", c_ushort),
            ("d_type", c_ubyte),
            ("d_name", char256),
        ]
    
    LinuxDirent64Ptr = POINTER(LinuxDirent64)
    
    libc_dll = this_process = CDLL(None, use_errno=True)
    # ALWAYS set argtypes and restype for functions, otherwise it's UB!!!
    opendir = libc_dll.opendir
    readdir = libc_dll.readdir
    closedir = libc_dll.closedir
    
    
    def get_dir_content(path):
        ret = [path, list(), list()]
        dir_stream = opendir(create_string_buffer(path.encode()))
        if (dir_stream == 0):
            print("opendir returned NULL (errno: {:d})".format(get_errno()))
            return ret
        set_errno(0)
        dirent_addr = readdir(dir_stream)
        while dirent_addr:
            dirent_ptr = cast(dirent_addr, LinuxDirent64Ptr)
            dirent = dirent_ptr.contents
            name = dirent.d_name.decode()
            if dirent.d_type & DT_DIR:
                if name not in (".", ".."):
                    ret[1].append(name)
            elif dirent.d_type & DT_REG:
                ret[2].append(name)
            dirent_addr = readdir(dir_stream)
        if get_errno():
            print("readdir returned NULL (errno: {:d})".format(get_errno()))
        closedir(dir_stream)
        return ret
    
    
    def main():
        print("{:s} on {:s}\n".format(sys.version, sys.platform))
        root_dir = "root_dir"
        entries = get_dir_content(root_dir)
        print(entries)
    
    
    if __name__ == "__main__":
        main()
    

    Notas :

    • Carga las tres funciones de libc (cargadas en el proceso actual) y las llama (para más detalles verifique [SO]: ¿Cómo verifico si un archivo existe sin excepciones? (respuesta de @CristiFati) - últimas notas del ítem #4. ). Eso colocaría este enfoque muy cerca del borde de Python / C
    • LinuxDirent64 es la representación ctypes 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 la estructura puede diferir y, de ser así, el alias de ctypes debe actualizarse; de ​​lo contrario, se producirá un comportamiento indefinido .
    • Devuelve datos en os.walkformato '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 :

    [[email protected]:~/Work/Dev/StackOverflow/q003207219]> ./code_ctypes.py
    3.5.2 (default, Nov 12 2018, 13:43:14)
    [GCC 5.4.0 20160609] on linux
    
    ['root_dir', ['dir2', 'dir1', 'dir3', 'dir0'], ['file1', 'file0']]
    


  1. [ActiveState.Docs]: win32file.FindFilesW ( específico de Win )

    Retrieves a list of matching filenames, using the Windows Unicode API. An interface to the API FindFirstFileW/FindNextFileW/Find close functions.


    >>> 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 long
    8
    >>> [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] not in (".", "..")]  # 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']
    

    Notas :


  1. Instale algún (otro) paquete de terceros que funcione
    • Lo más probable es que dependa de uno (o más) de los anteriores (quizás con ligeras personalizaciones)


Notas :

  • El código está destinado a ser portátil (excepto lugares que apuntan a un área específica, que están marcados) o cruzar:

    • plataforma ( Nix , Win ,)
    • Versión de Python (2, 3, )
  • Se usaron múltiples estilos de ruta (absoluto, relativo) en las variantes anteriores, para ilustrar el hecho de que las "herramientas" utilizadas son flexibles en esta dirección

  • os.listdiry os.scandiruse opendir / readdir / closedir ( [MS.Docs]: función FindFirstFileW / [MS.Docs]: función FindNextFileW / [MS.Docs]: función FindClose ) (a través de [GitHub]: python/cpython - (maestro) cpython/ Módulos/posixmodule.c )

  • win32file.FindFilesWtambién usa esas funciones ( específicas de Win ) (a través de [GitHub]: mhammond/pywin32 - (master) pywin32/win32/src/win32file.i )

  • _get_dir_content (desde el punto n .° 1 ) se puede implementar usando cualquiera de estos enfoques (algunos requerirán más trabajo y otros menos)

    • Se podría realizar un filtrado avanzado (en lugar de solo archivo frente a 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 vuelve el código, más tiempo llevará ejecutar
  • ¡Nota bene! Como se usa la recursión, 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 estaba alcanzando valores en algún lugar en el rango ( 990 .. 1000) ( recursionlimit - 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 recursión porque no tengo experiencia en el área (¿cuánto puedo aumentar antes de tener que aumentar también la pila en el sistema operativo ?level), pero en teoría siempre existirá 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: mantenerlo lo más simple y breve posible ). Para la producción , también se debe agregar el manejo de errores.

Otros enfoques:

  1. Use Python solo como contenedor

    • 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 del administrador del sistema :

      • Use Python (o cualquier lenguaje de programación para el caso) para ejecutar comandos de shell (y analizar sus resultados)
      • Algunos consideran que esto es un buen truco
      • Lo considero más como una solución poco convincente ( gainarie ), ya que la acción en sí 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 formateo de salida se podría hacer en ambos lados, pero no voy a insistir en eso. Además, usé deliberadamente en os.systemlugar de subprocess.Popen.
      (py35x64_test) E:\Work\Dev\StackOverflow\q003207219>"e:\Work\Dev\VEnvs\py35x64_test\Scripts\python.exe" -c "import os;os.system(\"dir /b root_dir\")"
      dir0
      dir1
      dir2
      dir3
      file0
      file1
      

    En general, este enfoque debe evitarse, ya que si algún formato de salida de comando difiere ligeramente entre las versiones/sabores 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 la uses glob()del módulo del mismo nombre. Esto le permite tener una coincidencia de patrones con *s.

Pero como otras personas señalaron en los comentarios, glob()puede tropezarse con direcciones de barra inconsistentes. Para ayudar con eso, le sugiero que use las funciones join()y en el módulo, y quizás también la función en el módulo.expanduser()os.pathgetcwd()os

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 se ha codificado 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 depende de 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 de 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 

Si está buscando una implementación Python de find , esta es una receta que uso con bastante frecuencia:

from findtools.find_files import (find_files, Match)

# Recursively find all *.sh files in **/usr/bin**
sh_files_pattern = Match(filetype='f', name='*.sh')
found_files = find_files(path='/usr/bin', match=sh_files_pattern)

for found_file in found_files:
    print found_file

Así que hice un paquete de PyPI y también hay un repositorio de GitHub . Espero que alguien lo encuentre potencialmente útil para este código.

Para obtener mejores resultados, puede usar listdir()el método del osmódulo junto con un generador (un generador es un poderoso iterador 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 sale de la función pero mantiene su estado actual y devuelve solo el nombre de la entrada detectada como un archivo. Todo lo anterior nos permite recorrer la función del generador.

Al devolver una lista de rutas de archivo absolutas, no se repite en subdirectorios

L = [os.path.join(os.getcwd(),f) for f in os.listdir('.') if os.path.isfile(os.path.join(os.getcwd(),f))]

Un sabio maestro me dijo una vez que:

When there are several established ways to do something, none of them is good for all cases.

Por lo tanto, agregaré una solución para un subconjunto del problema: muy a menudo, solo queremos verificar si un archivo coincide con una cadena de inicio y una cadena de fin, sin entrar en subdirectorios. Por lo tanto, nos gustaría una función que devuelva una lista de nombres de archivo, como:

filenames = dir_filter('foo/baz', radical='radical', extension='.txt')

Si desea declarar primero dos funciones, esto se puede hacer:

def file_filter(filename, radical='', extension=''):
    "Check if a filename matches a radical and extension"
    if not filename:
        return False
    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"
    if not 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 se mantengan siempre al principio o al final del nombre del archivo).

import os
import os.path


def get_files(target_dir):
    item_list = os.listdir(target_dir)

    file_list = list()
    for item in item_list:
        item_dir = os.path.join(target_dir,item)
        if os.path.isdir(item_dir):
            file_list += get_files(item_dir)
        else:
            file_list.append(item_dir)
    return file_list

Aquí uso una estructura recursiva.

Usando generadores

import os
def get_files(search_path):
     for (dirpath, _, filenames) in os.walk(search_path):
         for filename in filenames:
             yield os.path.join(dirpath, filename)
list_files = get_files('.')
for filename in list_files:
    print(filename)

Otra variante muy legible para Python 3.4+ es usar pathlib.Path.glob:

from pathlib import Path
folder = '/foo'
[f for f in Path(folder).glob('*') if f.is_file()]

Es fácil de 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 in Path(folder).glob('**/*.py') if not f.is_symlink()]

Para Python 2:

pip install rglob

Entonces hazlo

import rglob
file_list = rglob.rglob("/home/base/dir/", "*")
print file_list

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 descubrí que es 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 trazador de líneas de muestra donde la ruta de origen y el tipo de archivo se pueden proporcionar 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 escaneará 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.

dircache está "obsoleto desde la versión 2.6: el módulo dircache se eliminó en Python 3.0".

import dircache
list = dircache.listdir(pathname)
i = 0
check = len(list[0])
temp = []
count = len(list)
while count != 0:
  if len(list[i]) != check:
     temp.append(list[i-1])
     check = len(list[i])
  else:
    i = i + 1
    count = count - 1

print temp