Listar estrutura de árvore de diretório em python?


111

Eu sei que podemos usar os.walk()para listar todos os subdiretórios ou todos os arquivos em um diretório. No entanto, gostaria de listar o conteúdo completo da árvore do diretório:

- 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

Qual a melhor forma de conseguir isso em Python?

Respostas:


146

Esta é uma função para fazer isso com formatação:

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

1
Funcionou muito bem, obrigado. Embora a maioria saiba, ainda para o benefício dos iniciantes em python - observe que você precisará chamar a função no final (assumindo janelas), então você pode adicionar uma nova linha no final com o conteúdo list_files ("D: \\ ")
Rahul

1
Funcionou bem em python3. Mas em python2 ValueError: zero length field name in formaté lançado.
nipunasudha

3
Se startpath for repetido dentro do root, ele não substituirá cada ocorrência? Mudar para root.replace(startpath, '', 1)deve corrigir isso
drone.ah

31

Semelhante às respostas acima, mas para python3, indiscutivelmente legível e indiscutivelmente extensível:

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

Exemplo de uso:

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

Exemplo de saída:

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

Notas

  • Isso usa recursão. Irá gerar um RecursionError em árvores de pastas muito profundas
  • A árvore é avaliada preguiçosamente. Ele deve se comportar bem em árvores de pastas muito largas . Filhos imediatos de uma determinada pasta não são avaliados preguiçosamente.

Editar:

  • Bônus adicionado! critérios de retorno de chamada para filtrar caminhos.

Ótima ferramenta, você tem um exemplo rápido de como usar critérios para excluir nomes de pastas?
Matt-Mac-Muffin

Isso é exatamente o que eu estava procurando. Muito obrigado!
dheinz

24

Uma solução sem seu recuo:

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

os.walk já faz a caminhada de cima para baixo que você está procurando.

Ignorar a lista dirs evita a sobreposição que você mencionou.


2
python diz:NameError: name 'path' is not defined
Francesco Mantovani

1
@FrancescoMantovani "caminho" é a variável que contém o diretório que você deseja imprimir, ou seja, r "C: \ Usuários \ nome de usuário \ Documentos \ caminho"
Philly

16

Listar estrutura de árvore de diretório em Python?

Normalmente preferimos usar apenas a árvore GNU, mas nem sempre temos treeem todos os sistemas e, às vezes, o Python 3 está disponível. Uma boa resposta aqui poderia ser facilmente copiada e colada e não tornar o GNU treeum requisito.

treeA saída de é parecida com esta:

$ 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

Criei a estrutura de diretório acima em meu diretório inicial em um diretório que chamo pyscratch.

Também vejo outras respostas aqui que abordam esse tipo de saída, mas acho que podemos fazer melhor, com um código mais simples e moderno e abordagens de avaliação preguiçosas.

Árvore em Python

Para começar, vamos usar um exemplo que

  • usa o Pathobjeto Python 3
  • usa as expressões yielde yield from(que criam uma função geradora)
  • usa recursão para simplicidade elegante
  • usa comentários e algumas anotações de tipo para maior clareza
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)

e agora:

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

estampas:

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

Precisamos materializar cada diretório em uma lista porque precisamos saber quanto tempo ele é, mas depois jogamos a lista fora. Para uma recursão ampla e profunda, isso deve ser lento o suficiente.

O código acima, com os comentários, deve ser suficiente para entender completamente o que estamos fazendo aqui, mas sinta-se à vontade para percorrê-lo com um depurador para melhor controlá-lo se precisar.

Mais recursos

Agora, o GNU treenos oferece alguns recursos úteis que eu gostaria de ter com esta função:

  • imprime o nome do diretório de assunto primeiro (faz isso automaticamente, o nosso não)
  • imprime a contagem de n directories, m files
  • opção para limitar a recursão, -L level
  • opção de limitar apenas a diretórios, -d

Além disso, quando há uma árvore enorme, é útil limitar a iteração (por exemplo, com islice) para evitar travar seu interpretador com texto, pois em algum ponto a saída se torna muito prolixa para ser útil. Podemos tornar isso arbitrariamente alto por padrão - digamos 1000.

Portanto, vamos remover os comentários anteriores e preencher esta funcionalidade:

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

E agora podemos obter o mesmo tipo de saída que tree:

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

estampas:

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

E podemos restringir a níveis:

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

estampas:

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

4 directories, 3 files

E podemos limitar a saída aos diretórios:

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

estampas:

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

4 directories

Retrospectivo

Em retrospecto, poderíamos ter usado path.globpara correspondência. Também poderíamos usar path.rglobpara globbing recursivo, mas isso exigiria uma reescrita. Também poderíamos usar em itertools.teevez de materializar uma lista de conteúdo de diretório, mas isso poderia ter compensações negativas e provavelmente tornaria o código ainda mais complexo.

Comentários são bem vindos!


Para também imprimir as linhas de código, depois elif not limit_to_directories:adicione o seguinte: 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 link para obter os espaços em branco adequados.
Steven C. Howell

Isso era exatamente o que eu precisava em meu código e me ensinou alguns truques novos do Python! A única coisa que observo é que contentsprecisa ser filtrado se limit_to_directoriesfor True. Caso contrário, se uma pasta não tiver um diretório para o último arquivo, a árvore não será desenhada corretamente. if limit_to_directories: contents = [path for path in contents if path.is_dir()]
hennign

@hennign obrigado, resposta atualizada, aprecio o feedback!
Aaron Hall

O Python se baseia em list(dir_path.iterdir())retornar uma árvore de cima para baixo devidamente ordenada da estrutura de diretórios. Não vejo essa garantia na API para iterdir () . Forneça uma referência sobre como os iterdir()pedidos ou são garantidos para fornecer o pedido desejado.
ingyhere

@ingyhere Não tenho certeza de onde você tirou essa idéia - parece usar os.listdir()por padrão - o que não garante a ordem : "A lista está em ordem arbitrária e não inclui as entradas especiais '.' e '..' mesmo se estiverem presentes no diretório. "
Aaron Hall

15

Vim aqui procurando a mesma coisa e usei a resposta dhobbs para mim. Como forma de agradecer à comunidade, adicionei alguns argumentos para escrever em um arquivo, como akshay pediu, e tornei a exibição de arquivos opcional, para que não seja tão pouco uma saída. Também tornou o recuo um argumento opcional para que você possa alterá-lo, pois alguns gostam que seja 2 e outros preferem 4.

Usou loops diferentes para que aquele que não mostra os arquivos não verifique se precisa em cada iteração.

Espero que ajude alguém, já que dhobbs answer me ajudou. Muito obrigado.

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

Acho que essa resposta não contribui para a resposta já aceita. A única coisa que você está fornecendo é um código fluff adicional para desativar ou não recursos na resposta.
CodeLikeBeaker de

3
Seu sentimento está certo, @ jason-heine. A resposta aceita é boa o suficiente, mas algumas pessoas perguntaram como fazer essas coisas sem importância e eu queria dar algo a elas. Votar negativamente ou relatar minha resposta se você não quiser ver isso no SO, pensei que não faria mal, mas posso estar errado.
Rubén Cabrera

3
É realmente útil. Muito obrigado. Eu usei como está.
vladblindu 01 de

7

Com base nesta postagem fantástica

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

Aqui está um refinamento para se comportar exatamente como

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

#! / usr / bin / env python2 # - * - codificação: utf-8 - * -


# tree.py # # Escrito por Doug Dahms # # Imprime a estrutura da árvore para o caminho especificado na linha de comando





de os import listdir , sep
 de os . path import abspath , basename , isdir
 from sys import argv

def tree ( dir , padding , print_files = False , isLast = False , isFirst = False ): se isFirst : imprime padding . decodificar ( 'utf8' ) [: - 1 ]. encode ( 'utf8' ) + dir
     else : if isLast : imprime preenchimento . decodificar ( 'utf8' ) [: - 1 ].
    
         
        
             codificação ( 'utf8' ) + '└──' + basename ( abspath ( dir )) else : imprimir preenchimento . decodificar ( 'utf8' ) [: - 1 ]. encode ( 'utf8' ) + '├──' + basename ( abspath ( dir )) 
    files = [] if print_files : 
        files = listdir ( dir ) else :   
        
                
    
     
        files= [ x for x in listdir ( dir ) if isdir ( dir + sep + x )] se não isFirst : 
        padding = padding + '' 
    arquivos = ordenado ( arquivos , chave = lambda s : s . lower ()) 
    contagem = 0 
    last = len  
        (arquivos ) - 1 para i , arquivo em enumerar ( arquivos ): 
        contagem + = 1 
        caminho = dir + sep + arquivo  
     
        isLast = i == last
         if isdir ( path ): if count == len ( files ): if isFirst : 
                    tree ( path , padding , print_files , isLast , False ) else : 
                    tree ( path , padding + '' , print_files , isLast , False )
            
                 
                  
            else:
                tree(path, padding + '│', print_files, isLast, False)
        else:
            if isLast:
                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 and argv[1] == '-f':
        # print directories and files
        path = argv[2]
        if isdir(path):
            tree(path, '', True, False, True)
        else:
            print 'ERROR: \'' + path + '\' não é um diretório ' else : print usage ()
    
        

if __name__ == '__main__' : 
    main () 


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

Se alguém estiver interessado - essa função recursiva retorna uma estrutura aninhada de dicionários. As chaves são file systemnomes (de diretórios e arquivos), os valores são:

  • subdicionários para diretórios
  • strings para arquivos (ver file_token)

As strings que designam os arquivos estão vazias neste exemplo. Eles também podem receber, por exemplo, o conteúdo do arquivo ou as informações ou privilégios do proprietário ou qualquer objeto diferente de um dict. A menos que seja um dicionário, ele pode ser facilmente distinguido de um "tipo de diretório" em outras operações.

Ter essa árvore em um sistema de arquivos:

# 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

O 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': {}
}

Se você gosta disso, já criei um pacote (python 2 e 3) com isso (e um bom pyfakefsajudante): https://pypi.org/project/fsforge/


4

Além da resposta dhobbs acima ( https://stackoverflow.com/a/9728478/624597 ), aqui está uma funcionalidade extra de armazenamento de resultados em um arquivo (eu pessoalmente uso para copiar e colar no FreeMind para ter uma boa visão geral de a estrutura, portanto usei tabulações em vez de espaços para indentação):

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

essa resposta realmente ajudou, obrigado
prex

2

Você pode executar o comando 'tree' do shell do Linux.

Instalação:

   ~$sudo apt install tree

Usando em python

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

Exemplo:

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

Isso proporciona uma estrutura mais limpa e é visualmente mais abrangente e fácil de digitar.


Esta não é uma solução muito portátil, pois falha no Windows + depende de um programa adicional
oglop

2

Esta solução só funcionará se você tiver treeinstalado em seu sistema. No entanto, estou deixando esta solução aqui apenas no caso de ajudar outra pessoa.

Você pode dizer à árvore para gerar a estrutura da árvore como XML ( tree -X) ou JSON ( tree -J). JSON, é claro, pode ser analisado diretamente com Python e XML pode ser facilmente lido com lxml.

Com a seguinte estrutura de diretório como exemplo:

[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}
]

1

Talvez mais rápido do que @ellockie (talvez)

importar os
def file_writer (texto):
    com open ("folder_structure.txt", "a") como f_output:
        f_output.write (texto)
def list_files (startpath):


    para root, dirs, arquivos em os.walk (startpath):
        level = root.replace (startpath, '') .count (os.sep)
        recuo = '\ t' * 1 * (nível)
        output_string = '{} {} / \ n'.format (indent, os.path.basename (root))
        file_writer (output_string)
        subindent = '\ t' * 1 * (nível + 1)
        output_string = '% s% s \ n'% (subindent, [f for f in files])
        file_writer (''. join (output_string))


list_files ("/")

Resultados do teste na captura de tela abaixo:

insira a descrição da imagem aqui


0

Aqui você pode encontrar código com saída como esta: 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

0

Para quem ainda está procurando uma resposta. Aqui está uma abordagem recursiva para obter os caminhos em um dicionário.

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}

0

A resposta de @dhobbs é ótima!

mas simplesmente mude para fácil obter as informações do nível

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)

e a saída 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
================================================================

você pode obter o nível por |contagem!

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.