Listar la estructura del árbol de directorios en Python?

111

Sé que podemos usar os.walk()para enumerar todos los subdirectorios o todos los archivos de un directorio. Sin embargo, me gustaría enumerar el contenido completo del árbol de directorios:

- Subdirectory 1:
   - file11
   - file12
   - Sub-sub-directory 11:
         - file111
         - file112
- Subdirectory 2:
    - file21
    - sub-sub-directory 21
    - sub-sub-directory 22    
        - sub-sub-sub-directory 221
            - file 2211

¿Cuál es la mejor manera de lograr esto en Python?

cinny
fuente

Respuestas:

146

Aquí hay una función para hacer eso con el formateo:

import os

def list_files(startpath):
    for root, dirs, files in os.walk(startpath):
        level = root.replace(startpath, '').count(os.sep)
        indent = ' ' * 4 * (level)
        print('{}{}/'.format(indent, os.path.basename(root)))
        subindent = ' ' * 4 * (level + 1)
        for f in files:
            print('{}{}'.format(subindent, f))
dhobbs
fuente
1
Esto funcionó muy bien, gracias. Aunque la mayoría lo sabría, aún para el beneficio de los recién llegados a Python, tenga en cuenta que necesitaría llamar a la función al final (asumiendo Windows), por lo que puede agregar una nueva línea al final con el contenido list_files ("D: \\ ")
Rahul
1
Funcionó bien en python3. Pero en python2 ValueError: zero length field name in formatse lanza.
nipunasudha
3
Si startpath se repite dentro de la raíz, ¿no reemplazará cada aparición? Cambiar a root.replace(startpath, '', 1)debería arreglar eso
drone.ah
31

Similar a las respuestas anteriores, pero para python3, posiblemente legible y posiblemente extensible:

from pathlib import Path

class DisplayablePath(object):
    display_filename_prefix_middle = '├──'
    display_filename_prefix_last = '└──'
    display_parent_prefix_middle = '    '
    display_parent_prefix_last = '│   '

    def __init__(self, path, parent_path, is_last):
        self.path = Path(str(path))
        self.parent = parent_path
        self.is_last = is_last
        if self.parent:
            self.depth = self.parent.depth + 1
        else:
            self.depth = 0

    @property
    def displayname(self):
        if self.path.is_dir():
            return self.path.name + '/'
        return self.path.name

    @classmethod
    def make_tree(cls, root, parent=None, is_last=False, criteria=None):
        root = Path(str(root))
        criteria = criteria or cls._default_criteria

        displayable_root = cls(root, parent, is_last)
        yield displayable_root

        children = sorted(list(path
                               for path in root.iterdir()
                               if criteria(path)),
                          key=lambda s: str(s).lower())
        count = 1
        for path in children:
            is_last = count == len(children)
            if path.is_dir():
                yield from cls.make_tree(path,
                                         parent=displayable_root,
                                         is_last=is_last,
                                         criteria=criteria)
            else:
                yield cls(path, displayable_root, is_last)
            count += 1

    @classmethod
    def _default_criteria(cls, path):
        return True

    @property
    def displayname(self):
        if self.path.is_dir():
            return self.path.name + '/'
        return self.path.name

    def displayable(self):
        if self.parent is None:
            return self.displayname

        _filename_prefix = (self.display_filename_prefix_last
                            if self.is_last
                            else self.display_filename_prefix_middle)

        parts = ['{!s} {!s}'.format(_filename_prefix,
                                    self.displayname)]

        parent = self.parent
        while parent and parent.parent is not None:
            parts.append(self.display_parent_prefix_middle
                         if parent.is_last
                         else self.display_parent_prefix_last)
            parent = parent.parent

        return ''.join(reversed(parts))

Uso de ejemplo:

paths = DisplayablePath.make_tree(Path('doc'))
for path in paths:
    print(path.displayable())

Salida de ejemplo:

doc/
├── _static/
   ├── embedded/
      ├── deep_file
      └── very/
          └── deep/
              └── folder/
                  └── very_deep_file
   └── less_deep_file
├── about.rst
├── conf.py
└── index.rst

Notas

  • Esto usa recursividad. Generará un RecursionError en árboles de carpetas realmente profundos
  • El árbol se evalúa perezosamente. Debería comportarse bien en árboles de carpetas realmente anchos . Sin embargo, los hijos inmediatos de una carpeta determinada no se evalúan de forma perezosa.

Editar:

  • ¡Bonificación adicional! devolución de llamada de criterios para filtrar rutas.
abstrus
fuente
Buena herramienta, ¿tiene un ejemplo rápido sobre cómo utilizar criterios para excluir nombres de carpetas?
Matt-Mac-Muffin
Esto es exactamente lo que estaba buscando. Muchas gracias!
dheinz
24

Una solución sin su sangría:

for path, dirs, files in os.walk(given_path):
  print path
  for f in files:
    print f

os.walk ya realiza la caminata de arriba hacia abajo, primero en profundidad que está buscando.

Ignorar la lista de directorios evita la superposición que menciona.

Intra
fuente
2
pitón dice:NameError: name 'path' is not defined
Francesco Mantovani
1
@FrancescoMantovani "ruta" es la variable que contiene el directorio que desea imprimir, es decir, r "C: \ Users \ username \ Documents \ path"
Filadelfia
16

Listar la estructura del árbol de directorios en Python?

Por lo general, preferimos usar el árbol GNU, pero no siempre lo tenemos treeen todos los sistemas y, a veces, Python 3 está disponible. Una buena respuesta aquí podría copiarse y pegarse fácilmente y no convertir a GNU en treeun requisito.

treeLa salida se ve así:

$ tree
.
├── package
   ├── __init__.py
   ├── __main__.py
   ├── subpackage
      ├── __init__.py
      ├── __main__.py
      └── module.py
   └── subpackage2
       ├── __init__.py
       ├── __main__.py
       └── module2.py
└── package2
    └── __init__.py

4 directories, 9 files

Creé la estructura de directorio anterior en mi directorio de inicio en un directorio al que llamo pyscratch .

También veo otras respuestas aquí que se acercan a ese tipo de resultado, pero creo que podemos hacerlo mejor, con un código más simple y moderno y enfoques de evaluación perezosa.

Árbol en Python

Para empezar, usemos un ejemplo que

  • usa el Pathobjeto Python 3
  • usa las expresiones yieldy yield from(que crean una función generadora)
  • utiliza la recursividad para una simplicidad elegante
  • utiliza comentarios y algunas anotaciones de tipo para mayor claridad
from pathlib import Path

# prefix components:
space =  '    '
branch = '│   '
# pointers:
tee =    '├── '
last =   '└── '


def tree(dir_path: Path, prefix: str=''):
    """A recursive generator, given a directory Path object
    will yield a visual tree structure line by line
    with each line prefixed by the same characters
    """    
    contents = list(dir_path.iterdir())
    # contents each get pointers that are ├── with a final └── :
    pointers = [tee] * (len(contents) - 1) + [last]
    for pointer, path in zip(pointers, contents):
        yield prefix + pointer + path.name
        if path.is_dir(): # extend the prefix and recurse:
            extension = branch if pointer == tee else space 
            # i.e. space because last, └── , above so no more |
            yield from tree(path, prefix=prefix+extension)

y ahora:

for line in tree(Path.home() / 'pyscratch'):
    print(line)

huellas dactilares:

├── package
   ├── __init__.py
   ├── __main__.py
   ├── subpackage
      ├── __init__.py
      ├── __main__.py
      └── module.py
   └── subpackage2
       ├── __init__.py
       ├── __main__.py
       └── module2.py
└── package2
    └── __init__.py

Necesitamos materializar cada directorio en una lista porque necesitamos saber cuánto tiempo tiene, pero luego tiramos la lista. Para una recursividad amplia y profunda, esto debería ser lo suficientemente lento.

El código anterior, con los comentarios, debería ser suficiente para comprender completamente lo que estamos haciendo aquí, pero siéntase libre de revisarlo con un depurador para asimilarlo mejor si es necesario.

Más características

Ahora GNU treenos brinda un par de características útiles que me gustaría tener con esta función:

  • imprime primero el nombre del directorio del asunto (lo hace automáticamente, el nuestro no)
  • imprime el recuento de n directories, m files
  • opción para limitar la recursividad, -L level
  • opción de limitar solo a directorios, -d

Además, cuando hay un árbol enorme, es útil limitar la iteración (por ejemplo, con islice) para evitar bloquear su intérprete con texto, ya que en algún momento la salida se vuelve demasiado detallada para ser útil. Podemos hacer esto arbitrariamente alto por defecto, digamos 1000.

Así que eliminemos los comentarios anteriores y completemos esta funcionalidad:

from pathlib import Path
from itertools import islice

space =  '    '
branch = '│   '
tee =    '├── '
last =   '└── '
def tree(dir_path: Path, level: int=-1, limit_to_directories: bool=False,
         length_limit: int=1000):
    """Given a directory Path object print a visual tree structure"""
    dir_path = Path(dir_path) # accept string coerceable to Path
    files = 0
    directories = 0
    def inner(dir_path: Path, prefix: str='', level=-1):
        nonlocal files, directories
        if not level: 
            return # 0, stop iterating
        if limit_to_directories:
            contents = [d for d in dir_path.iterdir() if d.is_dir()]
        else: 
            contents = list(dir_path.iterdir())
        pointers = [tee] * (len(contents) - 1) + [last]
        for pointer, path in zip(pointers, contents):
            if path.is_dir():
                yield prefix + pointer + path.name
                directories += 1
                extension = branch if pointer == tee else space 
                yield from inner(path, prefix=prefix+extension, level=level-1)
            elif not limit_to_directories:
                yield prefix + pointer + path.name
                files += 1
    print(dir_path.name)
    iterator = inner(dir_path, level=level)
    for line in islice(iterator, length_limit):
        print(line)
    if next(iterator, None):
        print(f'... length_limit, {length_limit}, reached, counted:')
    print(f'\n{directories} directories' + (f', {files} files' if files else ''))

Y ahora podemos obtener el mismo tipo de resultado que tree:

tree(Path.home() / 'pyscratch')

huellas dactilares:

pyscratch
├── package
   ├── __init__.py
   ├── __main__.py
   ├── subpackage
      ├── __init__.py
      ├── __main__.py
      └── module.py
   └── subpackage2
       ├── __init__.py
       ├── __main__.py
       └── module2.py
└── package2
    └── __init__.py

4 directories, 9 files

Y podemos restringir a niveles:

tree(Path.home() / 'pyscratch', level=2)

huellas dactilares:

pyscratch
├── package
   ├── __init__.py
   ├── __main__.py
   ├── subpackage
   └── subpackage2
└── package2
    └── __init__.py

4 directories, 3 files

Y podemos limitar la salida a directorios:

tree(Path.home() / 'pyscratch', level=2, limit_to_directories=True)

huellas dactilares:

pyscratch
├── package
   ├── subpackage
   └── subpackage2
└── package2

4 directories

Retrospectivo

En retrospectiva, podríamos haber utilizado path.globpara emparejar. Quizás también podríamos usarlo path.rglobpara el globbing recursivo, pero eso requeriría una reescritura. También podríamos usaritertools.tee lugar de materializar una lista de contenidos de directorio, pero eso podría tener compensaciones negativas y probablemente haría el código aún más complejo.

¡Los comentarios son bienvenidos!

Aaron Hall
fuente
Para imprimir también las líneas de código, luego elif not limit_to_directories:agregue lo siguiente: info = prefix + pointer + path.name; try: with path.open('r') as f: n_lines = len(f.readlines()); loc = f' LOC: {n_lines}'; info += loc; except UnicodeDecodeError: pass; yield info Consulte este enlace para ver los espacios en blanco adecuados.
Steven C. Howell
¡Esto era exactamente lo que necesitaba en mi código y me enseñó algunos trucos nuevos de Python! Lo único que destacaría es que contentsdebe filtrarse si limit_to_directorieses Verdadero. De lo contrario, si una carpeta no tiene un directorio para el último archivo, el árbol no se dibujará correctamente. if limit_to_directories: contents = [path for path in contents if path.is_dir()]
Hennign
@hennign gracias, respuesta actualizada, ¡apreciamos los comentarios!
Aaron Hall
Python se basa en list(dir_path.iterdir())devolver un árbol de estructura de directorios de arriba hacia abajo ordenado correctamente. No veo tal garantía en la API para iterdir () . Proporcione una referencia sobre cómo se realiza el iterdir()pedido o se garantiza que proporcionará el pedido deseado.
ingyhere
@ingyhere No estoy seguro de dónde sacaste esa idea, parece que se usa os.listdir()de forma predeterminada , lo que no garantiza el orden : "La lista está en un orden arbitrario y no incluye las entradas especiales '.' y '..' incluso si están presentes en el directorio. "
Aaron Hall
15

Vine aquí buscando lo mismo y usé la respuesta dhobbs para mí. Como una forma de agradecer a la comunidad, agregué algunos argumentos para escribir en un archivo, como pidió akshay, e hice que mostrar archivos sea opcional para que no sea una salida. También hizo que la sangría sea un argumento opcional para que pueda cambiarlo, ya que a algunos les gusta que sea 2 y otros prefieren 4.

Usó diferentes bucles para que el que no muestra archivos no verifique si tiene que hacerlo en cada iteración.

Espero que ayude a alguien más como la respuesta de dhobbs me ayudó. Muchas gracias.

def showFolderTree(path,show_files=False,indentation=2,file_output=False):
"""
Shows the content of a folder in a tree structure.
path -(string)- path of the root folder we want to show.
show_files -(boolean)-  Whether or not we want to see files listed.
                        Defaults to False.
indentation -(int)- Indentation we want to use, defaults to 2.   
file_output -(string)-  Path (including the name) of the file where we want
                        to save the tree.
"""


tree = []

if not show_files:
    for root, dirs, files in os.walk(path):
        level = root.replace(path, '').count(os.sep)
        indent = ' '*indentation*(level)
        tree.append('{}{}/'.format(indent,os.path.basename(root)))

if show_files:
    for root, dirs, files in os.walk(path):
        level = root.replace(path, '').count(os.sep)
        indent = ' '*indentation*(level)
        tree.append('{}{}/'.format(indent,os.path.basename(root)))    
        for f in files:
            subindent=' ' * indentation * (level+1)
            tree.append('{}{}'.format(subindent,f))

if file_output:
    output_file = open(file_output,'w')
    for line in tree:
        output_file.write(line)
        output_file.write('\n')
else:
    # Default behaviour: print on screen.
    for line in tree:
        print line
Rubén Cabrera
fuente
Siento que esta respuesta no contribuye a la respuesta ya aceptada. Lo único que está proporcionando es un código adicional para desactivar funciones o no en la respuesta.
CodeLikeBeaker
3
Tu sentimiento es correcto, @ jason-heine. La respuesta aceptada es bastante buena, pero algunas personas preguntaron cómo hacer estas cosas suaves y yo quería darles algo. Votarlo o informar mi respuesta si no quiere ver esto en SO, pensé que no estaría de más, pero podría estar equivocado.
Rubén Cabrera
3
De hecho, es útil. Muchas gracias. Lo usé tal como está.
vladblindu
7

Basado en esta fantástica publicación

http://code.activestate.com/recipes/217212-treepy-graphically-displays-the-directory-structur/

Aquí hay un refinamiento para comportarse exactamente como

http://linux.die.net/man/1/tree

#! / usr / bin / env python2 # - * - codificación: utf-8 - * -


# tree.py # # Escrito por Doug Dahms # # Imprime la estructura de árbol para la ruta especificada en la línea de comando





desde os import listdir , sep
 desde os . ruta de importación abspath , basename , isdir
 de sys import argv

def tree ( dir , padding , print_files = False , isLast = False , isFirst = False ): if isFirst : imprimir padding . decode ( 'utf8' ) [: - 1 ( 'utf8' ) + '└──' + nombre base ( abspath ( dir )) else : relleno de impresión . decodificar ( 'utf8' ) [: -
    
         ]. encode ( 'utf8' ) + dir
     else : if isLast : imprimir relleno . decode ( 'utf8' ) [: - 1 ]. 
        
            encode 1 ]. encode ( 'utf8' ) + '├──' + nombre base ( abspath ( dir )) 
    archivos = [] if print_files : 
        files = listdir ( dir ) else :   
        
                
    
    
        files (= [ x para x en listdir ( dir ) if isdir ( dir + sep + x )] si no es isFirst : 
        padding = padding + '' 
    files = sorted ( files , key = lambda s : s . lower ()) 
    count = 0 
    last = archivos len ) -  
          1
     para i , file in enumerate ( files ): 
        count + = 1 
        path = dir + sep + file 
        isLast = i == last
         if isdir ( path ): if count == len ( files ): if isFirst : 
                    tree ( path , padding , print_files , isLast , False ) else : 
                    tree ( ruta , padding + '' , print_files , isLast , Falso )
            
                 
                  
             else : 
                tree ( path , padding + '│' , print_files , isLast , Falso ) más  
        : si es último :
            
                print padding + '└── ' + file
            else:
                print padding + '├── ' + file

def usage():
    return '''Usage: %s [-f] 
Print tree structure of path specified.
Options:
-f      Print files as well as directories
PATH    Path to process''' % basename(argv[0])

def main():
    if len(argv) == 1:
        print usage()
    elif len(argv) == 2:
        # print just directories
        path = argv[1]
        if isdir(path):
            tree(path, '', False, False, True)
        else:
            print 'ERROR: \'' + path + '\' is not a directory'
    elif len(argv) == 3 y argv [ 1 ] == '-f' : # imprimir directorios y archivos 
        ruta = argv [ 2 ] if isdir ( ruta ): 
            árbol ( ruta , '' , Verdadero , Falso   
        
           , True)
        else:
            print 'ERROR: \'' + path + '\' no es un directorio ' más : uso de impresión ()
    
        

if __name__ == '__main__' : 
    main () 

albfan
fuente
6
import os

def fs_tree_to_dict(path_):
    file_token = ''
    for root, dirs, files in os.walk(path_):
        tree = {d: fs_tree_to_dict(os.path.join(root, d)) for d in dirs}
        tree.update({f: file_token for f in files})
        return tree  # note we discontinue iteration trough os.walk

Si alguien está interesado, esa función recursiva devuelve una estructura anidada de diccionarios. Las claves son file systemnombres (de directorios y archivos), los valores son:

  • sub diccionarios para directorios
  • cadenas para archivos (ver file_token)

Las cadenas que designan archivos están vacías en este ejemplo. También se les puede dar, por ejemplo, el contenido del archivo o la información o privilegios de su propietario o cualquier objeto diferente a un dictado. A menos que sea un diccionario, se puede distinguir fácilmente de un "tipo de directorio" en operaciones posteriores.

Tener un árbol así en un sistema de archivos:

# bash:
$ tree /tmp/ex
/tmp/ex
├── d_a
   ├── d_a_a
   ├── d_a_b
      └── f1.txt
   ├── d_a_c
   └── fa.txt
├── d_b
   ├── fb1.txt
   └── fb2.txt
└── d_c

El resultado será:

# python 2 or 3:
>>> fs_tree_to_dict("/tmp/ex")
{
    'd_a': {
        'd_a_a': {},
        'd_a_b': {
            'f1.txt': ''
        },
        'd_a_c': {},
        'fa.txt': ''
    },
    'd_b': {
        'fb1.txt': '',
        'fb2.txt': ''
    },
    'd_c': {}
}

Si te gusta, ya he creado un paquete (python 2 y 3) con estas cosas (y un buen pyfakefsayudante): https://pypi.org/project/fsforge/

Mikaelblomkvistsson
fuente
4

Además de la respuesta de dhobbs anterior ( https://stackoverflow.com/a/9728478/624597 ), aquí hay una funcionalidad adicional para almacenar resultados en un archivo (yo personalmente lo uso para copiar y pegar en FreeMind para tener una buena descripción general de la estructura, por lo tanto, usé pestañas en lugar de espacios para la sangría):

import os

def list_files(startpath):

    with open("folder_structure.txt", "w") as f_output:
        for root, dirs, files in os.walk(startpath):
            level = root.replace(startpath, '').count(os.sep)
            indent = '\t' * 1 * (level)
            output_string = '{}{}/'.format(indent, os.path.basename(root))
            print(output_string)
            f_output.write(output_string + '\n')
            subindent = '\t' * 1 * (level + 1)
            for f in files:
                output_string = '{}{}'.format(subindent, f)
                print(output_string)
                f_output.write(output_string + '\n')

list_files(".")
ellockie
fuente
esta respuesta realmente ayudó, gracias
anterior
2

Puede ejecutar el comando 'árbol' del shell de Linux.

Instalación:

   ~$sudo apt install tree

Usando en Python

    >>> import os
    >>> os.system('tree <desired path>')

Ejemplo:

    >>> os.system('tree ~/Desktop/myproject')

Esto le brinda una estructura más limpia y es visualmente más completo y fácil de escribir.

Ashfaq Ur Rahman N
fuente
Esta no es una solución muy portátil ya que falla en Windows + depende de un programa adicional
oglop
2

Esta solución solo funcionará si la ha treeinstalado en su sistema. Sin embargo, dejo esta solución aquí en caso de que ayude a alguien más.

Puede indicarle al árbol que genere la estructura del árbol como XML ( tree -X) o JSON ( tree -J). Por supuesto, JSON se puede analizar directamente con python y XML se puede leer fácilmente lxml.

Con la siguiente estructura de directorios como ejemplo:

[sri@localhost Projects]$ tree --charset=ascii bands
bands
|-- DreamTroll
|   |-- MattBaldwinson
|   |-- members.txt
|   |-- PaulCarter
|   |-- SimonBlakelock
|   `-- Rob Stringer
|-- KingsX
|   |-- DougPinnick
|   |-- JerryGaskill
|   |-- members.txt
|   `-- TyTabor
|-- Megadeth
|   |-- DaveMustaine
|   |-- DavidEllefson
|   |-- DirkVerbeuren
|   |-- KikoLoureiro
|   `-- members.txt
|-- Nightwish
|   |-- EmppuVuorinen
|   |-- FloorJansen
|   |-- JukkaNevalainen
|   |-- MarcoHietala
|   |-- members.txt
|   |-- TroyDonockley
|   `-- TuomasHolopainen
`-- Rush
    |-- AlexLifeson
    |-- GeddyLee
    `-- NeilPeart

5 directories, 25 files

XML

<?xml version="1.0" encoding="UTF-8"?>
<tree>
  <directory name="bands">
    <directory name="DreamTroll">
      <file name="MattBaldwinson"></file>
      <file name="members.txt"></file>
      <file name="PaulCarter"></file>
      <file name="RobStringer"></file>
      <file name="SimonBlakelock"></file>
    </directory>
    <directory name="KingsX">
      <file name="DougPinnick"></file>
      <file name="JerryGaskill"></file>
      <file name="members.txt"></file>
      <file name="TyTabor"></file>
    </directory>
    <directory name="Megadeth">
      <file name="DaveMustaine"></file>
      <file name="DavidEllefson"></file>
      <file name="DirkVerbeuren"></file>
      <file name="KikoLoureiro"></file>
      <file name="members.txt"></file>
    </directory>
    <directory name="Nightwish">
      <file name="EmppuVuorinen"></file>
      <file name="FloorJansen"></file>
      <file name="JukkaNevalainen"></file>
      <file name="MarcoHietala"></file>
      <file name="members.txt"></file>
      <file name="TroyDonockley"></file>
      <file name="TuomasHolopainen"></file>
    </directory>
    <directory name="Rush">
      <file name="AlexLifeson"></file>
      <file name="GeddyLee"></file>
      <file name="NeilPeart"></file>
    </directory>
  </directory>
  <report>
    <directories>5</directories>
    <files>25</files>
  </report>
</tree>

JSON

[sri@localhost Projects]$ tree -J bands
[
  {"type":"directory","name":"bands","contents":[
    {"type":"directory","name":"DreamTroll","contents":[
      {"type":"file","name":"MattBaldwinson"},
      {"type":"file","name":"members.txt"},
      {"type":"file","name":"PaulCarter"},
      {"type":"file","name":"RobStringer"},
      {"type":"file","name":"SimonBlakelock"}
    ]},
    {"type":"directory","name":"KingsX","contents":[
      {"type":"file","name":"DougPinnick"},
      {"type":"file","name":"JerryGaskill"},
      {"type":"file","name":"members.txt"},
      {"type":"file","name":"TyTabor"}
    ]},
    {"type":"directory","name":"Megadeth","contents":[
      {"type":"file","name":"DaveMustaine"},
      {"type":"file","name":"DavidEllefson"},
      {"type":"file","name":"DirkVerbeuren"},
      {"type":"file","name":"KikoLoureiro"},
      {"type":"file","name":"members.txt"}
    ]},
    {"type":"directory","name":"Nightwish","contents":[
      {"type":"file","name":"EmppuVuorinen"},
      {"type":"file","name":"FloorJansen"},
      {"type":"file","name":"JukkaNevalainen"},
      {"type":"file","name":"MarcoHietala"},
      {"type":"file","name":"members.txt"},
      {"type":"file","name":"TroyDonockley"},
      {"type":"file","name":"TuomasHolopainen"}
    ]},
    {"type":"directory","name":"Rush","contents":[
      {"type":"file","name":"AlexLifeson"},
      {"type":"file","name":"GeddyLee"},
      {"type":"file","name":"NeilPeart"}
    ]}
  ]},
  {"type":"report","directories":5,"files":25}
]
musaraña
fuente
1

Quizás más rápido que @ellockie (Quizás)

importar sistema operativo
def file_writer (texto):
    con open ("folder_structure.txt", "a") como f_output:
        f_output.write (texto)
def list_files (ruta de inicio):


    para root, dirs, archivos en os.walk (startpath):
        nivel = root.replace (ruta de inicio, '') .count (os.sep)
        sangría = '\ t' * 1 * (nivel)
        output_string = '{} {} / \ n'.format (sangría, os.path.basename (root))
        redactor_archivo (cadena_salida)
        subindent = '\ t' * 1 * (nivel + 1)
        output_string = '% s% s \ n'% (subindent, [f para f en archivos])
        file_writer (''. join (salida_cadena))


list_files ("/")

Resultados de la prueba en la captura de pantalla a continuación:

ingrese la descripción de la imagen aquí

Enes ERGUN
fuente
0

Aquí puede encontrar un código con un resultado como este: https://stackoverflow.com/a/56622847/6671330

V .
|-> V folder1
|   |-> V folder2
|   |   |-> V folder3
|   |   |   |-> file3.txt
|   |   |-> file2.txt
|   |-> V folderX
|   |-> file1.txt
|-> 02-hw1_wdwwfm.py
|-> 06-t1-home1.py
|-> 06-t1-home2.py
|-> hw1.py
Igor Z
fuente
0

Para aquellos que todavía buscan una respuesta. Aquí hay un enfoque recursivo para obtener las rutas en un diccionario.

import os


def list_files(startpath):
    for root, dirs, files in os.walk(startpath):
        dir_content = []
        for dir in dirs:
            go_inside = os.path.join(startpath, dir)
            dir_content.append(list_files(go_inside))
        files_lst = []
        for f in files:
            files_lst.append(f)
        return {'name': root, 'files': files_lst, 'dirs': dir_content}
cielo
fuente
0

¡La respuesta de @dhobbs es genial!

pero simplemente cambia para obtener fácilmente la información del nivel

def print_list_dir(dir):
    print("=" * 64)
    print("[PRINT LIST DIR] %s" % dir)
    print("=" * 64)
    for root, dirs, files in os.walk(dir):
        level = root.replace(dir, '').count(os.sep)
        indent = '| ' * level
        print('{}{} \\'.format(indent, os.path.basename(root)))
        subindent = '| ' * (level + 1)
        for f in files:
            print('{}{}'.format(subindent, f))
    print("=" * 64)

y la salida como

================================================================
[PRINT LIST DIR] ./
================================================================
 \
| os_name.py
| json_loads.py
| linspace_python.py
| list_file.py
| to_gson_format.py
| type_convert_test.py
| in_and_replace_test.py
| online_log.py
| padding_and_clipping.py
| str_tuple.py
| set_test.py
| script_name.py
| word_count.py
| get14.py
| np_test2.py
================================================================

¡puedes obtener el nivel por |conteo!

Colin Wang
fuente