Lista struktury drzewa katalogów w Pythonie?

111

Wiem, że możemy użyć os.walk()do wyświetlenia wszystkich podkatalogów lub wszystkich plików w katalogu. Chciałbym jednak wymienić pełną zawartość drzewa katalogów:

- 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

Jak najlepiej to osiągnąć w Pythonie?

cinny
źródło

Odpowiedzi:

146

Oto funkcja, która robi to z formatowaniem:

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
źródło
1
Bardzo dobrze, dziękuję. Chociaż większość by wiedziała, nadal dla korzyści nowicjuszy w Pythonie - pamiętaj, że musiałbyś wywołać funkcję na końcu (zakładając okna), więc możesz dodać nową linię na końcu z treścią list_files ("D: \\ ”)
Rahul
1
Działał dobrze na Pythonie3. Ale na python2 ValueError: zero length field name in formatzostaje wyrzucony.
nipunasudha
3
Jeśli startpath zostanie powtórzona w katalogu głównym, czy nie zastąpi każdego wystąpienia? Zmiana na root.replace(startpath, '', 1)powinna to naprawić
drone.ah
32

Podobny do odpowiedzi powyżej, ale dla pythona3, prawdopodobnie czytelny i prawdopodobnie rozszerzalny:

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

Przykładowe użycie:

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

Przykładowe dane wyjściowe:

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

Uwagi

  • To używa rekurencji. Podniesie RecursionError na naprawdę głębokich drzewach folderów
  • Drzewo jest leniwie oceniane. Powinien dobrze zachowywać się na naprawdę szerokich drzewach folderów. Bezpośrednie elementy podrzędne danego folderu nie są jednak leniwie oceniane.

Edytować:

  • Dodatkowy bonus! kryteria wywołania zwrotnego do filtrowania ścieżek.
abstrus
źródło
Niezłe narzędzie, czy masz szybki przykład, jak używać kryteriów w celu wykluczania nazw folderów?
Matt-Mac-Muffin
To jest dokładnie to, czego szukałem. Dziękuję bardzo!
dheinz
24

Rozwiązanie bez wcięcia:

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

os.walk wykonuje już poszukiwany spacer z góry na dół, w głąb.

Ignorowanie listy katalogów zapobiega nakładaniu się, o którym wspomniałeś.

Intra
źródło
2
Python mówi:NameError: name 'path' is not defined
Francesco Mantovani
1
@FrancescoMantovani "path" to zmienna zawierająca katalog, który chcesz wydrukować, tj. R "C: \ Users \ nazwa_użytkownika \ Dokumenty \ ścieżka"
zwelz
16

Lista struktury drzewa katalogów w Pythonie?

Zwykle wolimy po prostu używać drzewa GNU, ale nie zawsze mamy go treew każdym systemie, a czasami Python 3 jest dostępny. Dobra odpowiedź w tym miejscu może być łatwo skopiowana i wklejona, a GNU nie będzie treewymaganiem.

treeWynik wygląda następująco:

$ 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

Utworzyłem powyższą strukturę katalogów w moim katalogu domowym w katalogu, który wywołuję pyscratch.

Widzę tu również inne odpowiedzi, które podchodzą do tego rodzaju wyników, ale myślę, że możemy zrobić to lepiej, stosując prostszy, nowocześniejszy kod i leniwie oceniające podejścia.

Drzewo w Pythonie

Na początek użyjmy tego przykładu

  • używa Pathobiektu Python 3
  • używa wyrażeń yieldi yield from(które tworzą funkcję generatora)
  • używa rekurencji dla eleganckiej prostoty
  • używa komentarzy i niektórych adnotacji dla większej przejrzystości
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)

i teraz:

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

wydruki:

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

Musimy zmaterializować każdy katalog w postaci listy, ponieważ musimy wiedzieć, jak długi jest, ale później wyrzucamy listę. W przypadku głębokiej i szerokiej rekurencji powinno to być wystarczająco leniwe.

Powyższy kod wraz z komentarzami powinien wystarczyć, aby w pełni zrozumieć, co tutaj robimy, ale nie krępuj się go przejść za pomocą debugera, aby lepiej go zebrać, jeśli zajdzie taka potrzeba.

Więcej funkcji

Teraz GNU treedaje nam kilka przydatnych funkcji, które chciałbym mieć dzięki tej funkcji:

  • wypisuje najpierw nazwę katalogu tematycznego (robi to automatycznie, nasz nie)
  • wypisuje liczbę n directories, m files
  • możliwość ograniczenia rekursji, -L level
  • możliwość ograniczenia tylko do katalogów, -d

Ponadto, gdy istnieje ogromne drzewo, warto ograniczyć iterację (np. Za pomocą islice), aby uniknąć blokowania interpretera tekstem, ponieważ w pewnym momencie dane wyjściowe stają się zbyt szczegółowe, aby były przydatne. Domyślnie możemy ustawić to arbitralnie wysoko - powiedzmy 1000.

Usuńmy więc poprzednie komentarze i wypełnijmy tę funkcjonalność:

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

Teraz możemy uzyskać takie same wyniki, jak tree:

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

wydruki:

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

Możemy ograniczyć się do poziomów:

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

wydruki:

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

4 directories, 3 files

Możemy ograniczyć dane wyjściowe do katalogów:

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

wydruki:

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

4 directories

Z mocą wsteczną

Z perspektywy czasu mogliśmy użyć path.globdo dopasowania. Moglibyśmy również użyć path.rglobdo rekurencyjnego globbingu, ale wymagałoby to przepisania. Moglibyśmy również użyć itertools.teezamiast materializowania listy zawartości katalogu, ale mogłoby to mieć negatywne kompromisy i prawdopodobnie uczyniłoby kod jeszcze bardziej złożonym.

Komentarze są mile widziane!

Aaron Hall
źródło
Aby również wydrukować wiersze kodu, po elif not limit_to_directories:dodaniu następujących elementów: 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 Zobacz to łącze, aby uzyskać prawidłowe odstępy.
Steven C. Howell
To było dokładnie to, czego potrzebowałem w swoim kodzie i nauczył mnie kilku nowych sztuczek Pythona! Jedyną rzeczą, którą chciałbym zauważyć, jest to, że contentsmusi być filtrowane, jeśli limit_to_directoriesma wartość True. W przeciwnym razie, jeśli folder nie ma katalogu na ostatni plik, drzewo nie zostanie poprawnie narysowane. if limit_to_directories: contents = [path for path in contents if path.is_dir()]
Hennign
@hennign thanks, odpowiedź zaktualizowana, doceniaj opinie!
Aaron Hall
Cały Python jest oparty na list(dir_path.iterdir())zwracaniu odpowiednio uporządkowanego odgórnego drzewa struktury katalogów. Nie widzę takiej gwarancji w API dla iterdir () . Proszę podać odniesienie, w jaki sposób iterdir()zamawia się lub gwarantuje, że zapewni żądane zamówienie.
ingyhere
@ingyhere Nie jestem pewien, skąd wziął się ten pomysł - wydaje się, że jest używany os.listdir()domyślnie - co nie gwarantuje kolejności : „Lista jest w dowolnej kolejności i nie zawiera wpisów specjalnych”. i „..”, nawet jeśli znajdują się w katalogu. "
Aaron Hall
15

Przyszedłem tutaj, szukając tego samego i użyłem dla mnie odpowiedzi dhobbs. Aby podziękować społeczności, dodałem kilka argumentów do zapisu do pliku, zgodnie z prośbą Akshay, i uczyniłem wyświetlanie plików opcjonalnymi, aby nie było to tak bitowe wyjście. Ustawiono również wcięcie jako opcjonalny argument, więc możesz go zmienić, ponieważ niektórzy lubią 2, a inni wolą 4.

Używał różnych pętli, więc ta, która nie wyświetla plików, nie sprawdza, czy musi przy każdej iteracji.

Mam nadzieję, że pomoże to komuś innemu, ponieważ pomogła mi odpowiedź dhobbsa. Wielkie dzięki.

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
źródło
Czuję, że ta odpowiedź nie przyczynia się do już zaakceptowanej odpowiedzi. Jedyną rzeczą, którą podajesz, jest dodatkowy kod niepotrzebny, aby wyłączyć funkcje lub nie w odpowiedzi.
CodeLikeBeaker
3
Twoje przeczucie jest właściwe, @ jason-heine. Przyjęta odpowiedź jest wystarczająca, ale niektórzy pytali, jak zrobić takie puchate rzeczy i chciałem im coś dać. Odrzuć to lub zgłoś moją odpowiedź, jeśli nie chcesz tego widzieć w SO, myślałem, że to nie zaszkodzi, ale mogę się mylić.
Rubén Cabrera
3
Rzeczywiście jest to przydatne. Wielkie dzięki. Użyłem go takim, jakim jest.
vladblindu
7

Na podstawie tego fantastycznego postu

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

Oto wyrafinowanie, aby zachowywać się dokładnie tak

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

#! / usr / bin / env python2 # - * - kodowanie: utf-8 - * -


# tree.py # # Napisane przez Douga Dahmsa # # Drukuje strukturę drzewa dla ścieżki określonej w wierszu poleceń





z katalogu importu systemu operacyjnego , oddzielony od katalogu
 z systemem operacyjnym . path import abspath , basename , isdir
 from sys import argv

def tree ( dir , padding , print_files = False , isLast = False , isFirst = False ): if isFirst : print padding . decode ( „utf8” ) [: - 1 ]. encode ( 'utf8' ) + dir
     else : if isLast : print padding . decode ( „utf8” ) [: - 1 ].
    
         
        
            encode ( 'utf8' ) + '└──' + basename ( abspath ( dir )) else : print padding . decode ( „utf8” ) [: - 1 ]. encode ( 'utf8' ) + '├──' + basename ( abspath ( dir )) 
    files = [] if print_files : 
        files = listdir ( dir ) else :   
        
                
    
    
        Pliki = [ x o x w listdir ( dir ) jeśli isdir ( dir + września + x )] Jeśli nie isfirst : 
        wyściółka = wyściółka + '' 
    pliki = klasyfikowane ( plików , klucz = N y : y . niższe ()) 
    liczyć = 0 
    last = len (  
       files ) - 1 for 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 ( path , padding + '' , print_files , isLast , Fałsz )
            
                 
                  
            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 + '\' nie jest katalogiem ' else : print use ()
    
        

if __name__ == '__main__' : 
    main () 

albfan
źródło
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

Jeśli ktoś jest zainteresowany - ta funkcja rekurencyjna zwraca zagnieżdżoną strukturę słowników. Klucze to file systemnazwy (katalogów i plików), wartościami są:

  • sub słowniki dla katalogów
  • ciągi do plików (zobacz file_token)

W tym przykładzie ciągi oznaczające pliki są puste. Mogą to być także np. Dane zawartości pliku lub informacje o jego właścicielu lub uprawnienia lub obiekt inny niż dict. O ile nie jest to słownik, można go łatwo odróżnić od „typu katalogu” w dalszych operacjach.

Posiadanie takiego drzewa w systemie plików:

# 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

Rezultatem będzie:

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

Jeśli ci się to podoba, utworzyłem już pakiet (python 2 i 3) z tymi rzeczami (i fajnym pyfakefspomocnikiem): https://pypi.org/project/fsforge/

Mikaelblomkvistsson
źródło
4

Oprócz powyższej odpowiedzi dhobbsa ( https://stackoverflow.com/a/9728478/624597 ), tutaj jest dodatkowa funkcja przechowywania wyników w pliku (osobiście używam jej do kopiowania i wklejania do FreeMind, aby mieć ładny przegląd strukturę, dlatego użyłem tabulatorów zamiast spacji dla wcięć):

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
źródło
ta odpowiedź naprawdę pomogła, dzięki
prex
2

Możesz wykonać polecenie „drzewo” powłoki Linuksa.

Instalacja:

   ~$sudo apt install tree

Używanie w Pythonie

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

Przykład:

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

Zapewnia to czystszą strukturę, jest wizualnie bardziej wszechstronna i łatwa do wpisania.

Ashfaq Ur Rahman N
źródło
To nie jest zbyt przenośne rozwiązanie, ponieważ to nie działa w systemie Windows + polega na dodatkowym programie
oglop
2

To rozwiązanie będzie działać tylko wtedy, gdy treezainstalowałeś w swoim systemie. Jednak zostawiam to rozwiązanie na wypadek, gdyby komuś pomogło.

Możesz powiedzieć drzewu, aby wyświetlało strukturę drzewa jako XML ( tree -X) lub JSON ( tree -J). JSON można oczywiście analizować bezpośrednio w Pythonie, a XML można łatwo odczytać za pomocą lxml.

Na przykładzie następującej struktury katalogów:

[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}
]
złośnica
źródło
1

Może szybciej niż @ellockie (może)

import os
def file_writer (tekst):
    z open ("folder_structure.txt", "a") jako f_output:
        f_output.write (tekst)
def list_files (startpath):


    dla root, dirs, files in os.walk (startpath):
        level = root.replace (startpath, '') .count (os.sep)
        indent = '\ t' * 1 * (poziom)
        output_string = '{} {} / \ n'.format (wcięcie, os.path.basename (root))
        file_writer (łańcuch_wyjściowy)
        subindent = '\ t' * 1 * (poziom + 1)
        output_string = '% s% s \ n'% (podcięcie, [f dla f w plikach])
        file_writer (''. join (łańcuch_wyjściowy))


list_files („/”)

Wyniki testu na zrzucie ekranu poniżej:

wprowadź opis obrazu tutaj

Enes ERGUN
źródło
0

Tutaj możesz znaleźć kod z następującymi danymi wyjściowymi: 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
źródło
0

Dla tych, którzy wciąż szukają odpowiedzi. Oto rekurencyjne podejście do pobierania ścieżek w słowniku.

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}
niebo
źródło
0

Odpowiedź @ dhobbs jest świetna!

ale po prostu zmień na łatwe, aby uzyskać informacje o poziomie

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)

i wyjście podobne

================================================================
[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
================================================================

możesz uzyskać poziom według |liczby!

Colin Wang
źródło