Verzeichnisbaumstruktur in Python auflisten?


111

Ich weiß, dass wir damit os.walk()alle Unterverzeichnisse oder alle Dateien in einem Verzeichnis auflisten können. Ich möchte jedoch den vollständigen Inhalt des Verzeichnisbaums auflisten:

- 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

Wie erreicht man dies am besten in Python?

Antworten:


146

Hier ist eine Funktion, um dies mit der Formatierung zu tun:

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
Das hat sehr gut funktioniert, danke. Obwohl die meisten wissen würden, dass Python-Neulinge immer noch davon profitieren - bitte beachten Sie, dass Sie die Funktion am Ende aufrufen müssen (unter der Annahme von Fenstern), damit Sie am Ende möglicherweise eine neue Zeile mit dem Inhalt list_files ("D: \\ ")
Rahul

1
Funktionierte gut auf Python3. Aber auf Python2 ValueError: zero length field name in formatwird geworfen.
Nipunasudha

3
Wenn der Startpfad innerhalb von root wiederholt wird, ersetzt er nicht jedes Vorkommen? Das Ändern zu root.replace(startpath, '', 1)sollte das beheben
drone.ah

31

Ähnlich wie bei den obigen Antworten, jedoch für Python3, wohl lesbar und wohl erweiterbar:

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

Anwendungsbeispiel:

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

Beispielausgabe:

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

Anmerkungen

  • Dies verwendet Rekursion. Es wird ein RecursionError für wirklich tiefe Ordnerbäume ausgelöst
  • Der Baum wird träge ausgewertet. Es sollte sich auf wirklich breiten Ordnerbäumen gut verhalten . Sofortige Kinder eines bestimmten Ordners werden jedoch nicht träge ausgewertet.

Bearbeiten:

  • Bonus hinzugefügt! Kriterien-Rückruf zum Filtern von Pfaden.

Nettes Tool, haben Sie ein kurzes Beispiel, wie Sie Kriterien verwenden, um Ordnernamen auszuschließen?
Matt-Mac-Muffin

Genau das habe ich gesucht. Ich danke dir sehr!
Dheinz

24

Eine Lösung ohne Einrückung:

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

os.walk macht bereits den Top-Down-Spaziergang, den Sie suchen.

Das Ignorieren der Verzeichnisliste verhindert die von Ihnen erwähnte Überlappung.


2
Python sagt:NameError: name 'path' is not defined
Francesco Mantovani

1
@FrancescoMantovani "Pfad" ist die Variable, die das Verzeichnis enthält, das Sie drucken möchten, dh "C: \ Benutzer \ Benutzername \ Dokumente \ Pfad"
Philly

16

Verzeichnisbaumstruktur in Python auflisten?

Wir bevorzugen normalerweise nur die Verwendung des GNU-Baums, haben dies jedoch nicht immer treeauf jedem System, und manchmal ist Python 3 verfügbar. Eine gute Antwort hier könnte leicht kopiert werden und GNU nicht treezur Anforderung machen.

treeDie Ausgabe sieht folgendermaßen aus:

$ 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

Ich habe die obige Verzeichnisstruktur in meinem Home-Verzeichnis unter einem von mir aufgerufenen Verzeichnis erstellt pyscratch.

Ich sehe hier auch andere Antworten, die sich dieser Art von Ausgabe nähern, aber ich denke, wir können es besser machen, mit einfacherem, modernerem Code und trägen Bewertungen von Ansätzen.

Baum in Python

Lassen Sie uns zunächst ein Beispiel dafür verwenden

  • verwendet das Python 3- PathObjekt
  • verwendet die Ausdrücke yieldund yield from(die eine Generatorfunktion erstellen)
  • verwendet Rekursion für elegante Einfachheit
  • Verwendet Kommentare und einige Typanmerkungen für zusätzliche Klarheit
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)

und nun:

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

Drucke:

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

Wir müssen jedes Verzeichnis in einer Liste materialisieren, weil wir wissen müssen, wie lange es dauert, aber danach werfen wir die Liste weg. Für eine tiefe und breite Rekursion sollte dies faul genug sein.

Der obige Code mit den Kommentaren sollte ausreichen, um vollständig zu verstehen, was wir hier tun. Sie können ihn jedoch auch mit einem Debugger durchgehen, um ihn bei Bedarf besser zu überprüfen.

Mehr Funktionen

Jetzt treebietet uns GNU einige nützliche Funktionen, die ich mit dieser Funktion haben möchte:

  • druckt zuerst den Betreff-Verzeichnisnamen aus (dies geschieht automatisch, bei uns nicht)
  • druckt die Anzahl von n directories, m files
  • Option zur Begrenzung der Rekursion, -L level
  • Option auf nur Verzeichnisse zu beschränken, -d

Wenn es einen großen Baum gibt, ist es auch nützlich, die Iteration (z. B. mit islice) zu begrenzen , um zu vermeiden, dass Ihr Interpreter mit Text blockiert wird, da die Ausgabe irgendwann zu ausführlich wird, um nützlich zu sein. Wir können dies standardmäßig beliebig hoch machen - sagen wir 1000.

Entfernen wir also die vorherigen Kommentare und füllen Sie diese Funktion aus:

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

Und jetzt können wir die gleiche Art von Ausgabe erhalten wie tree:

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

Drucke:

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

Und wir können uns auf Ebenen beschränken:

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

Drucke:

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

4 directories, 3 files

Und wir können die Ausgabe auf Verzeichnisse beschränken:

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

Drucke:

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

4 directories

Rückblick

Im Nachhinein hätten wir das path.globMatching verwenden können. Wir könnten es vielleicht auch path.rglobfür rekursives Globbing verwenden, aber das würde ein Umschreiben erfordern. Wir könnten auch itertools.teeeine Liste von Verzeichnisinhalten verwenden, anstatt sie zu materialisieren, aber das könnte negative Kompromisse haben und den Code wahrscheinlich noch komplexer machen.

Kommentare sind willkommen!


Um auch die Linien-of-Code zu drucken, nachdem elif not limit_to_directories:fügen Sie die folgende: 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 Siehe diesen Link für die richtige white-space.
Steven C. Howell

Dies war genau das, was ich in meinem Code brauchte und brachte mir einige neue Python-Tricks bei! Ich würde nur bemerken, dass contentsgefiltert werden muss, wenn limit_to_directoriesTrue ist. Andernfalls wird der Baum nicht korrekt gezeichnet, wenn ein Ordner kein Verzeichnis für die letzte Datei enthält. if limit_to_directories: contents = [path for path in contents if path.is_dir()]
28.

@hennign danke, Antwort aktualisiert, freue mich über das Feedback!
Aaron Hall

Python basiert auf der list(dir_path.iterdir())Rückgabe eines ordnungsgemäß geordneten Top-Down-Baums der Verzeichnisstruktur. Ich sehe keine solche Garantie in der API für iterdir () . Bitte geben Sie an, wie iterdir()Bestellungen oder garantiert die gewünschte Bestellung liefern.
Ingyhere

@ingyhere Ich bin mir nicht sicher, woher Sie diese Idee haben - sie scheint os.listdir()standardmäßig zu verwenden - , die keine Garantie für die Reihenfolge gibt : "Die Liste ist in beliebiger Reihenfolge und enthält keine speziellen Einträge '.' und '..' auch wenn sie im Verzeichnis vorhanden sind. "
Aaron Hall

15

Ich kam hierher, um das Gleiche zu suchen und benutzte Dhobbs Antwort für mich. Um der Community zu danken, habe ich einige Argumente hinzugefügt, um in eine Datei zu schreiben, wie akshay gefragt hat, und das Anzeigen von Dateien optional gemacht, damit es nicht so sehr eine Ausgabe ist. Außerdem wurde der Einzug zu einem optionalen Argument gemacht, damit Sie ihn ändern können, da einige es als 2 und andere als 4 bevorzugen.

Es wurden verschiedene Schleifen verwendet, sodass diejenige, die keine Dateien anzeigt, nicht bei jeder Iteration prüft, ob dies erforderlich ist.

Hoffe, es hilft jemand anderem, da Dhobbs Antwort mir geholfen hat. Vielen Dank.

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

Ich bin der Meinung, dass diese Antwort nicht zur bereits akzeptierten Antwort beiträgt. Das einzige, was Sie bereitstellen, ist zusätzlicher Fluff-Code, um Funktionen auszuschalten oder nicht in der Antwort.
CodeLikeBeaker

3
Dein Gefühl ist richtig, @ Jason-Heine. Die akzeptierte Antwort ist gut genug, aber einige Leute fragten, wie man dieses Flusenzeug macht, und ich wollte ihnen etwas geben. Stimmen Sie ab oder melden Sie meine Antwort, wenn Sie dies nicht in SO sehen möchten. Ich dachte, es würde nicht schaden, aber ich könnte mich irren.
Rubén Cabrera

3
Es ist in der Tat nützlich. Vielen Dank. Ich habe es so benutzt wie es ist.
Vladblindu

7

Basierend auf diesem fantastischen Beitrag

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

Hier ist es eine Verfeinerung, sich genau so zu verhalten

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

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


# tree.py # # Geschrieben von Doug Dahms # # Druckt die Baumstruktur für den in der Befehlszeile angegebenen Pfad





von os import listdir , sep
 von os . Pfad Import abspath , Basisnamen , isdir
 von sys import argv

def Baum ( dir , Padding , print_files = Falsch , isLast = Falsch , isFirst = Falsch ): wenn isFirst : Druck padding . decodieren ( 'utf8' ) [: - 1 ]. kodieren ( 'UTF - 8' ) + dir
     anders : wenn isLast : Druckpolster . decodieren ( 'utf8' ) [: - 1 ].
    
         
        
            encode ( 'utf8' ) + '└──' + basename ( abspath ( dir )) else : print padding . decodieren ( 'utf8' ) [: - 1 ]. encode ( 'utf8' ) + '├──' + basename ( abspath ( dir )) 
    files = [] wenn print_files : 
        files = listdir ( dir ) else :   
        
                
    
    
        Dateien = [ x für x in listdir ( dir ) , wenn isdir ( dir + September + x )] , wenn nicht isFirst : 
        padding = padding + '' 
    Dateien = sortiert ( Dateien , Schlüssel = Lambda s : s . senken ()) 
    zählen = 0 
    last = len (  
       Dateien ) - + file  1 für i , Datei in Aufzählung ( Dateien ): 
        count + = 1 
        path = dir + sep
     
        isLast = i == last
         if isdir ( Pfad ): if count == len ( Dateien ): if isFirst : 
                    Baum ( Pfad , Auffüllen , Druckdateien , isLast , False ) else : 
                    Baum ( Pfad , Auffüllen + '' , Druckdateien , isLast , Falsch )
            
                 
                  
             else : 
                Baum ( Weg , 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'
    eliflen ( argv ) == 3 und argv [ 1 ] == '-f' : # Verzeichnisse und Dateien drucken 
        path = argv [ 2 ] if isdir ( path ): 
            tree ( path , '' , True , False , True ) else : print     
        
            
        
             'ERROR: \'' + path + '\' ist kein Verzeichnis '
    sonst : Druck Nutzung ()
        

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

Wenn jemand interessiert ist, gibt diese rekursive Funktion eine verschachtelte Struktur von Wörterbüchern zurück. Schlüssel sind file systemNamen (von Verzeichnissen und Dateien), Werte sind entweder:

  • Unterwörterbücher für Verzeichnisse
  • Zeichenfolgen für Dateien (siehe file_token)

Die Zeichenfolgen, die Dateien kennzeichnen, sind in diesem Beispiel leer. Sie können auch z. B. Dateiinhalte oder deren Eigentümerinformationen oder -berechtigungen oder ein anderes Objekt als ein Diktat erhalten. Sofern es sich nicht um ein Wörterbuch handelt, kann es in weiteren Vorgängen leicht von einem "Verzeichnis-Typ" unterschieden werden.

Einen solchen Baum in einem Dateisystem haben:

# 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

Das Ergebnis wird sein:

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

Wenn Ihnen das gefällt, habe ich bereits ein Paket (Python 2 & 3) mit diesem Zeug (und einem netten pyfakefsHelfer) erstellt: https://pypi.org/project/fsforge/


4

Neben der obigen Antwort von dhobbs ( https://stackoverflow.com/a/9728478/624597 ) gibt es hier eine zusätzliche Funktion zum Speichern von Ergebnissen in einer Datei (ich persönlich verwende sie zum Kopieren und Einfügen in FreeMind , um einen schönen Überblick zu erhalten die Struktur, deshalb habe ich Tabulatoren anstelle von Leerzeichen zum Einrücken verwendet):

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

Diese Antwort hat wirklich geholfen, danke
prex

2

Sie können den Befehl 'tree' der Linux-Shell ausführen.

Installation:

   ~$sudo apt install tree

Verwendung in Python

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

Beispiel:

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

Dies gibt Ihnen eine sauberere Struktur und ist visuell umfassender und einfach zu tippen.


Dies ist keine sehr portable Lösung, da dies unter Windows + fehlschlägt und auf einem zusätzlichen Programm beruht
oglop

2

Diese Lösung funktioniert nur, wenn Sie treeauf Ihrem System installiert haben . Ich lasse diese Lösung jedoch hier, nur für den Fall, dass sie jemand anderem hilft.

Sie können tree anweisen, die Baumstruktur als XML ( tree -X) oder JSON ( tree -J) auszugeben . JSON kann natürlich direkt mit Python analysiert werden und XML kann leicht mit gelesen werden lxml.

Am Beispiel der folgenden Verzeichnisstruktur:

[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

Vielleicht schneller als @ellockie (Vielleicht)

os importieren
def file_writer (text):
    mit open ("folder_structure.txt", "a") als f_output:
        f_output.write (Text)
def list_files (Startpfad):


    für root, dirs, Dateien in os.walk (Startpfad):
        level = root.replace (Startpfad, '') .count (os.sep)
        Einzug = '\ t' * 1 * (Ebene)
        output_string = '{} {} / \ n'.format (Einzug, os.path.basename (root))
        file_writer (output_string)
        subindent = '\ t' * 1 * (Stufe + 1)
        output_string = '% s% s \ n'% (Unterindent, [f für f in Dateien])
        file_writer (''. join (output_string))


list_files ("/")

Testergebnisse im folgenden Screenshot:

Geben Sie hier die Bildbeschreibung ein


0

Hier finden Sie Code mit folgender Ausgabe: 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

Für diejenigen, die noch nach einer Antwort suchen. Hier ist ein rekursiver Ansatz, um die Pfade in einem Wörterbuch abzurufen.

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

@ dhobbs Antwort ist großartig!

aber ändern Sie einfach, um einfach die Level-Informationen zu erhalten

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)

und die Ausgabe wie

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

Sie können das Level durch |Zählen erhalten!

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.