Python'da dizin ağacı yapısını listelemek?


111

Bir os.walk()dizindeki tüm alt dizinleri veya tüm dosyaları listelemek için kullanabileceğimizi biliyorum . Bununla birlikte, tam dizin ağacı içeriğini listelemek istiyorum:

- 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

Bunu Python'da en iyi şekilde nasıl başarabilirim?

Yanıtlar:


147

Biçimlendirmeyle bunu yapmak için bir işlev:

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
Bu çok iyi çalıştı, teşekkürler. Çoğu kişi biliyor olsa da, yine de python'a yeni gelenlerin yararı için - lütfen sonunda işlevi çağırmanız gerektiğini unutmayın (pencereler varsayarak), bu nedenle sonuna içerik list_files ("D: \\ ")
Rahul

1
Python3 üzerinde iyi çalıştı. Ancak python2'de ValueError: zero length field name in formatfırlatılır.
nipunasudha

3
Başlangıç ​​yolu kök içinde tekrarlanırsa, her bir oluşumun yerini almaz mı? Değiştirmek root.replace(startpath, '', 1)bunu düzeltmeli
drone.ah

32

Yukarıdaki cevaplara benzer, ancak python3 için, tartışmalı bir şekilde okunabilir ve tartışılabilir bir şekilde genişletilebilir:

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

Örnek kullanım:

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

Örnek çıktı:

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

Notlar

  • Bu, özyinelemeyi kullanır. Gerçekten derin klasör ağaçlarında bir Özyineleme Hatası yükseltecek
  • Ağaç tembel olarak değerlendirilir. Gerçekten geniş klasör ağaçlarında iyi davranmalıdır . Bununla birlikte, belirli bir klasörün acil çocukları tembel olarak değerlendirilmez.

Düzenle:

  • Bonus eklendi! filtreleme yolları için ölçüt geri araması.

Güzel araç, klasör adlarını hariç tutmak için kriterlerin nasıl kullanılacağına dair hızlı bir örneğiniz var mı?
Matt-Mac-Muffin

Bu tam olarak aradığım şeydi. Çok teşekkür ederim!
dheinz

24

Girintiniz olmayan bir çözüm:

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

os.walk, aradığınız yukarıdan aşağıya derinlik yürüyüşünü zaten yapıyor.

Dizinler listesinin yok sayılması, bahsettiğiniz örtüşmeleri engeller.


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

1
@FrancescoMantovani "yol", yazdırmak istediğiniz dizini içeren değişkendir, yani r "C: \ Kullanıcılar \ kullanıcı adı \ Belgeler \ yol"
zwelz

16

Python'da dizin ağacı yapısını listelemek ister misiniz?

Genellikle sadece GNU ağacını kullanmayı tercih ederiz, ancak treeher sistemde her zaman bulunmayabilir ve bazen Python 3 kullanılabilir. Buradaki iyi bir cevap, kolayca kopyalanıp yapıştırılabilir ve GNU'yu treebir gereksinim haline getirmeyebilir .

treeçıktısı şuna benzer:

$ 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

Yukarıdaki dizin yapısını ana dizinimde aradığım bir dizin altında oluşturdum pyscratch.

Burada bu tür çıktılara yaklaşan başka yanıtlar da görüyorum, ancak bence daha basit, daha modern kod ve tembel değerlendirme yaklaşımları ile daha iyisini yapabiliriz.

Python'da Ağaç

Başlamak için bir örnek verelim.

  • Python 3 Pathnesnesini kullanır
  • yieldve yield fromifadelerini kullanır (bir oluşturucu işlevi oluşturan)
  • zarif bir sadelik için özyinelemeyi kullanır
  • Ekstra netlik için yorumlar ve bazı tür ek açıklamaları kullanır
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)

ve şimdi:

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

baskılar:

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

Her dizini bir liste halinde düzenlememiz gerekiyor çünkü ne kadar uzun olduğunu bilmemiz gerekiyor, ancak daha sonra listeyi atıyoruz. Derin ve geniş özyineleme için bu yeterince tembel olmalıdır.

Yorumlarla birlikte yukarıdaki kod, burada ne yaptığımızı tam olarak anlamak için yeterli olmalıdır, ancak gerekirse daha iyi bir şekilde düzeltmek için bir hata ayıklayıcı ile adım adım ilerlemekten çekinmeyin.

Daha fazla özellik

Şimdi GNU treebize bu işlevle sahip olmak istediğim birkaç yararlı özellik sunuyor:

  • önce konu dizin adını yazdırır (bunu otomatik olarak yapar, bizimki yazmaz)
  • sayısını yazdırır n directories, m files
  • özyinelemeyi sınırlama seçeneği, -L level
  • sadece dizinlerle sınırlama seçeneği, -d

Ayrıca, büyük bir ağaç olduğunda, isliceyorumlayıcınızı metinle kilitlemekten kaçınmak için yinelemeyi sınırlamak (örn. İle) yararlıdır , çünkü bir noktada çıktı yararlı olamayacak kadar ayrıntılı hale gelir. Bunu varsayılan olarak rastgele yüksek yapabiliriz - diyelim 1000.

Öyleyse önceki yorumları kaldıralım ve bu işlevi dolduralım:

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

Ve şimdi aynı tür çıktıyı elde edebiliriz tree:

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

baskılar:

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

Ve seviyelerle sınırlayabiliriz:

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

baskılar:

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

4 directories, 3 files

Ve çıktıyı dizinlerle sınırlayabiliriz:

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

baskılar:

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

4 directories

Geriye dönük

Geriye dönüp baktığımızda, path.globeşleştirme için kullanabilirdik. path.rglobÖzyinelemeli globbing için de kullanabiliriz , ancak bunun yeniden yazılması gerekir. itertools.teeBir dizin içeriği listesi oluşturmak yerine kullanabiliriz , ancak bu olumsuz ödünleşmelere sahip olabilir ve muhtemelen kodu daha da karmaşık hale getirebilir.

Yorumlara açığız!


Kod satırlarını da yazdırmak için elif not limit_to_directories:aşağıdakileri ekledikten sonra : Uygun beyaz boşluk için bu bağlantıyainfo = 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 bakın .
Steven C. Howell

Kodumda tam olarak ihtiyacım olan şey buydu ve bana yeni Python hileleri öğretti! Not edeceğim tek şey, contentseğer limit_to_directoriesTrue ise filtrelenmesi gerektiğidir . Aksi takdirde, bir klasörün son dosya için bir dizini yoksa, ağaç doğru şekilde çizilmez. if limit_to_directories: contents = [path for path in contents if path.is_dir()]
hennign

@hennign teşekkürler, cevap güncellendi, geri bildirimler için teşekkür ederiz!
Aaron Hall

Python, list(dir_path.iterdir())düzgün sıralı bir yukarıdan aşağıya dizin yapısı ağacı döndürmeye dayanır . Gördüğüm böyle bir garanti de iterdir için API () . Lütfen iterdir()siparişlerin nasıl sağlanacağına veya istenen siparişi vermenin garantili olduğuna dair bir referans sağlayın.
ingyhere

@ingyhere Bu fikri nereden edindiğinizden emin değilim - varsayılan olarak kullanılıyor gibi görünüyoros.listdir() - bu da siparişin garantisini vermiyor: "Liste keyfi sıradadır ve özel girişleri içermez '.' ve '..' dizinde bulunsalar bile. "
Aaron Hall

15

Buraya aynı şeyi aramaya geldim ve benim için dhobbs cevabını kullandım. Topluluğa teşekkür etmenin bir yolu olarak, akshay'ın sorduğu gibi bir dosyaya yazmak için bazı argümanlar ekledim ve dosyaları göstermeyi isteğe bağlı yaptım, bu yüzden o kadar da bit bir çıktı değil. Ayrıca girintiyi isteğe bağlı bir argüman yaptı, böylece onu değiştirebilirsiniz, çünkü bazıları 2 olmasını ve diğerleri 4'ü tercih eder.

Dosyaları göstermeyen, her yinelemede olması gerekip gerekmediğini kontrol etmemesi için farklı döngüler kullandı.

Umarım dhobbs cevabı bana yardımcı olduğu için başka birine yardımcı olur. Çok teşekkürler.

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

Bu cevabın zaten kabul edilmiş cevaba katkıda bulunmadığını hissediyorum. Sağladığınız tek şey, yanıtta özellikleri kapatmak veya kapatmamak için ek tüy kodudur.
CodeLikeBeaker

3
Duyguların doğru @ jason-heine. Kabul edilen cevap yeterince iyi, ancak bazıları bu tüylü şeyleri nasıl yapacaklarını sordu ve ben de onlara bir şey vermek istedim. Bunu SO'da görmek istemiyorsanız, olumsuz oy verin veya cevabımı bildirin, zarar vermeyeceğini düşündüm, ama yanılıyor olabilirim.
Rubén Cabrera

3
Gerçekten faydalıdır. Çok teşekkürler. Olduğu gibi kullandım.
vladblindu

7

Bu harika gönderiye dayanarak

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

İşte tam olarak böyle davranmak için bir incelik

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

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


# tree.py # # Doug Dahms tarafından yazılmıştır # # Komut satırında belirtilen yol için ağaç yapısını yazdırır





dan os ithalat listdir , sep
 gelen os . yol içe aktarma abspath , basename , isdir
 from sys import argv

def ağaç ( dir , padding , print_files = False , isLast = False , isFirst = False ): if isFirst : baskı dolgusu . decode ( 'utf8' ) [: - 1 ]. kodlamak ( 'utf8' ) + dir
     başka : eğer islast : Baskı dolgu . decode ( 'utf8' ) [: - 1 ].
    
         
        
            encode ( 'utf8' ) + '└──' + basename ( abspath ( dir )) else : baskı dolgusu . decode ( 'utf8' ) [: - 1 ]. encode ( 'utf8' ) + '├──' + basename ( abspath ( dir )) 
    dosyalar = [] eğer print_files : 
        files = listdir ( dir ) else :   
        
                
    
    
        dosyaları = [ X için X de listdir ( dir ) halinde isdir ( dir + Eylül + X )] Eğer değil isFirst : 
        dolgu = dolgu + ' 
    dosyaları = kriteri ( dosya , anahtar = lambda s : s . alt ()) 
    sayısı = 0 
    son = uzunluk (  
       dosyalar ) - 1 için i , dosya içinde enumerate ( dosyalar ): 
        sayım + = 1 
        yol = dir + Eylül + dosya  
     
        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 , Yanlış )
            
                 
                  
            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 + '\' bir dizin değil ' aksi takdirde : yazdırma kullanımı ()
    
        

eğer __name__ == '__main__' : 
    Ana () 


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

İlgilenen varsa - bu özyinelemeli işlev sözlüklerin iç içe geçmiş yapısını döndürür. Anahtarlar file systemadlardır (dizinlerin ve dosyaların), değerler şunlardan biridir:

  • dizinler için alt sözlükler
  • dosyalar için dizeler (bkz. file_token)

Dosyaları belirten dizeler bu örnekte boştur. Bunlara ayrıca örneğin dosya içerikleri veya sahip bilgileri veya ayrıcalıkları veya bir dikteden farklı herhangi bir nesne verilebilir. Bir sözlük olmadığı sürece, sonraki işlemlerde bir "dizin türü" nden kolayca ayırt edilebilir.

Dosya sisteminde böyle bir ağacın olması:

# 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

Sonuç şu şekilde olacaktır:

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

Bundan hoşlanıyorsanız, bu şeyle (ve güzel bir pyfakefsyardımcı) zaten bir paket (python 2 ve 3) oluşturdum : https://pypi.org/project/fsforge/


4

Yukarıdaki dhobbs yanıtına ek olarak ( https://stackoverflow.com/a/9728478/624597 ), burada sonuçları bir dosyaya depolamanın ek bir işlevselliği var (şahsen bunu FreeMind'a kopyalayıp yapıştırmak için kullanıyorum . yapı, bu nedenle girinti için boşluklar yerine sekmeler kullandım):

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

bu cevap gerçekten yardımcı oldu, teşekkürler
prex

2

Linux kabuğunun 'ağaç' komutunu çalıştırabilirsiniz.

Kurulum:

   ~$sudo apt install tree

Python'da kullanmak

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

Misal:

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

Bu size daha temiz bir yapı sağlar ve görsel olarak daha kapsamlı ve yazması kolaydır.


Windows'ta başarısız olduğu için bu çok taşınabilir bir çözüm değil + ek programa dayanıyor
oglop

2

Bu çözüm yalnızca treesisteminize kurduysanız işe yarayacaktır . Ancak, başka birine yardım etmesi durumunda bu çözümü burada bırakıyorum.

Ağaca ağaç yapısını XML ( tree -X) veya JSON ( tree -J) olarak vermesini söyleyebilirsiniz . Tabii ki JSON doğrudan python ile ayrıştırılabilir ve XML ile kolayca okunabilir lxml.

Örnek olarak aşağıdaki dizin yapısıyla:

[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

@Ellockie'den daha hızlı (Belki)

işletim sistemini içe aktar
def file_writer (metin):
    f_output olarak open ("klasör_yapı.txt", "a") ile:
        f_output.write (metin)
def list_files (başlangıç ​​yolu):


    root, dirs, os.walk'taki dosyalar (başlangıç ​​yolu) için:
        level = root.replace (startpath, '') .count (os.sep)
        girinti = '\ t' * 1 * (düzey)
        output_string = '{} {} / \ n'.format (girinti, os.path.basename (kök))
        file_writer (çıktı_dizesi)
        altindent = '\ t' * 1 * (düzey + 1)
        output_string = '% s% s \ n'% (alt indent, [dosyalardaki f için f])
        file_writer (''. join (output_string))


list_files ("/")

Test sonuçları aşağıdaki ekran görüntüsünde:

görüntü açıklamasını buraya girin


0

Burada çıktıya sahip kodu şu şekilde bulabilirsiniz: 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

Hâlâ cevap arayanlar için. İşte bir sözlükteki yolları elde etmek için yinelemeli bir yaklaşım.

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'ın cevabı harika!

ancak seviye bilgilerini almak için basitçe değiştirin

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)

ve çıktı gibi

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

Seviyeyi |sayarak alabilirsiniz!

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.