Перелічити структуру дерева каталогів у python?


111

Я знаю, що ми можемо використовувати os.walk()для переліку всіх підкаталогів або всіх файлів у каталозі. Однак я хотів би перерахувати повний вміст дерева каталогів:

- 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

Як найкраще досягти цього в Python?

Відповіді:


146

Ось функція зробити це за допомогою форматування:

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
Це спрацювало дуже добре, дякую. Хоча більшість знає, але все-таки на користь новачків у python - зауважте, що вам потрібно буде викликати функцію наприкінці (припускаючи вікна), тож ви можете додати новий рядок наприкінці зі списком вмісту list_files ("D: \\ ")
Рахул

1
Добре працював на python3. Але на python2 ValueError: zero length field name in formatпотрапляє.
nipunasudha

3
Якщо стартовий шлях повторюється в корені, чи не замінить він кожне виникнення? Перехід до root.replace(startpath, '', 1)повинен виправити це
drone.ah

31

Схожий на відповіді вище, але для python3, можливо, читабельний і, можливо, розширюваний:

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

Приклад використання:

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

Приклад виводу:

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

Примітки

  • Для цього використовується рекурсія. Це дійсно підніме RecursionError глибоких деревах папок
  • Дерево ліниво оцінено. Він повинен добре поводитися на дуже широких деревах папок. Негайні діти даної папки, однак, не лінь оцінюються.

Редагувати:

  • Доданий бонус! зворотний виклик критеріїв для фільтрування контурів.

Гарний інструмент, чи є у вас короткий приклад того, як використовувати критерії, щоб виключити імена папок?
Метт-Мак-Маффін

Це саме те, що я шукав. Дуже дякую!
dheinz

24

Рішення без відступу:

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

os.walk вже робить ходу зверху вниз, першу глибину, яку ви шукаєте.

Ігнорування списку брудів запобігає збігу, який ви згадуєте.


2
python каже:NameError: name 'path' is not defined
Франческо Мантовані

1
@FrancescoMantovani "path" - це змінна, що містить каталог, який ви бажаєте надрукувати, тобто r "C: \ Users \ username \ Documents \ path"
zwelz

16

Список дерев структури каталогів у Python?

Зазвичай ми вважаємо за краще використовувати дерево GNU, але це не завжди treeв кожній системі, а іноді Python 3 доступний. Хороша відповідь тут може бути легко скопійована і не висуває GNU treeвимогою.

treeВихідний результат виглядає приблизно так:

$ 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

Я створив вищевказану структуру каталогів у своєму домашньому каталозі під каталогом, який я викликаю pyscratch.

Я також бачу тут інші відповіді, які підходять до такого виду, але я думаю, що ми можемо зробити краще, простішим, сучаснішим кодом та ліниво оцінюючими підходами.

Дерево в Пітоні

Для початку скористаємося прикладом

  • використовує Pathоб’єкт Python 3
  • використовує вирази yieldта yield from(які створюють функцію генератора)
  • використовує рекурсію для елегантної простоти
  • використовує коментарі та деякі примітки для додаткової чіткості
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)

а зараз:

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

відбитки:

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

Нам потрібно матеріалізувати кожен каталог у список, тому що нам потрібно знати, скільки він триває, але згодом ми його викидаємо. Для глибокої та широкої рекурсії це повинно бути досить ледачим.

Вищенаведений код із коментарями повинен бути достатнім, щоб повністю зрозуміти, що ми тут робимо, але сміливо переступайте через нього налагоджувачем, щоб краще розібратися, якщо вам потрібно.

Більше можливостей

Тепер GNU treeнадає нам кілька корисних функцій, які я хотів би мати за допомогою цієї функції:

  • спочатку виводить ім'я каталогу тематики (робить це автоматично, наше - ні)
  • друкує кількість n directories, m files
  • можливість обмеження рекурсії, -L level
  • можливість обмежитися лише каталогами, -d

Крім того, коли є величезне дерево, корисно обмежити ітерацію (наприклад, з islice), щоб уникнути блокування перекладача текстом, оскільки в якийсь момент висновок стає надто багатослівним, щоб бути корисним. Ми можемо зробити це довільно високим за замовчуванням - скажімо 1000.

Тож давайте видалимо попередні коментарі та заповніть цю функціональність:

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

І тепер ми можемо отримати такий же вихід, як tree:

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

відбитки:

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

І ми можемо обмежитися рівнями:

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

відбитки:

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

4 directories, 3 files

І ми можемо обмежити вихід на каталоги:

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

відбитки:

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

4 directories

Ретроспектива

В ретроспективі ми могли б використовувати path.globдля узгодження. Ми також можемо використовувати path.rglobдля рекурсивного глобалізації, але це вимагатиме перезапису. Ми також могли б скористатисяitertools.tee замість того, щоб оформити список вмісту каталогів, але це може мати негативні компроміси і, ймовірно, зробить код ще складнішим.

Коментарі вітаються!


Щоб також надрукувати рядки коду, elif not limit_to_directories:додайте наступне: 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 Дивіться це посилання для належного пробілу.
Стівен К. Хоуелл

Це саме те, що мені потрібно було в моєму коді, і навчив мене новим трюкам Python! Єдине, що я зазначу, це те, що contentsйого потрібно відфільтрувати, якщо limit_to_directoriesце правда. В іншому випадку, якщо в папці немає каталогу для останнього файлу, дерево не буде намальовано правильно. if limit_to_directories: contents = [path for path in contents if path.is_dir()]
хничний

@hennign спасибі, відповідь оновлена, оцініть відгуки!
Аарон Холл

Все Python передбачає list(dir_path.iterdir())повернення правильно впорядкованого дерева зверху структури каталогів. Я не бачу такої гарантії в API для iterdir () . Будь ласка, надайте довідку про те, як iterdir()замовляти чи гарантовано забезпечувати бажане замовлення.
ingyhere

@ingyhere Я не впевнений, звідки ви взяли таку ідею - вона, мабуть, використовується os.listdir()за замовчуванням - що не дає гарантії для замовлення : "Список у довільному порядку і не містить спеціальних записів". та "..", навіть якщо вони є в каталозі. "
Аарон Холл

15

Я прийшов сюди шукати те ж саме і використав dhobbs відповідь для мене. Як спосіб подякувати спільноті, я додав кілька аргументів, щоб записати у файл, як попросив akshay, і зробив показ файлів необов’язковим, так що це не так битовий вихід. Також зробив відступ необов’язковим аргументом, щоб ви могли його змінити, оскільки деяким подобається, що це 2, а іншим більше 4.

Використовуються різні петлі, тому той, що не відображає файли, не перевіряє, чи потрібно це робити на кожній ітерації.

Сподіваюся, це допомагає комусь іншому, як мені допомогла відповідь dhobbs. Дуже дякую.

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

Я думаю, що ця відповідь не сприяє вже прийнятій відповіді. Єдине, що ви надаєте, - це додатковий код, щоб вимкнути функції або не відповісти.
CodeLikeBeaker

3
Ваше почуття правильне, @ jason-heine. Прийнята відповідь досить хороша, але деякі люди запитували, як це зробити з пухом, і я хотів щось їм дати. Відхиліть це або повідомте про свою відповідь, якщо ви не хочете бачити це в ТАК, я думав, що це не зашкодить, але я можу помилитися.
Рубен Кабрера

3
Це дійсно корисно. Дуже дякую. Я використовував його як є.
vladblindu

7

На основі цієї фантастичної публікації

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

Тут є уточнення, щоб вести себе точно так

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

#! / usr / bin / env python2 # - * - кодування: utf-8 - * -


# tree.py # # Автор Doug Dahms # # Друкує структуру дерева для шляху, вказаного в командному рядку





from os import listdir , sep
 від os . шлях імпорту abspath , базове ім'я , isdir
 від sys import argv

Захист дерево ( реж , оббивка , print_files = Брехня , isLast = Помилковий , IsFirst = Помилковий ): якщо IsFirst : друк набивка . декодування ( 'utf8' ) [: - 1 ]. закодувати ( 'utf8' ) + реж
     ще : якщо isLast : друк набивка . декодування ( 'utf8' ) [: - 1 ].
    
         
        
             кодування ( 'utf8' ) + '└──' + базове ім'я ( abspath ( реж )) ще : друк набивка . декодування ( 'utf8' ) [: - 1 ]. кодують ( 'utf8' ) + '├──' + BASENAME ( abspath ( реж )) 
    файли = [] , якщо print_files : 
        файли = listdir ( реж ) ще :   
        
                
    
    
        files (= [ x for x in listdir ( dir ) if isdir ( dir + sep + x )] if not isFirst : 
        padding = padding + '' 
    файли = відсортовано ( файли , ключ = лямбда s : s . нижній ()) 
    count = 0 
    last = len  
       файли ) - file  1 для i , файл у перерахуванні ( файли ): 
        count + = 1 
        path = dir + sep +
     
        isLast = я == останній
         якщо такі isdir ( шлях ): якщо лічильник == Len ( файли ): якщо IsFirst : 
                    дерево ( шлях , оббивка , print_files , isLast , Помилкові ) ще : 
                    дерево ( шлях , оббивка + '' , print_files , isLast , Помилково )
            
                 
                  
            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 + '\' не є каталогом ' else : print use ()
    
        

якщо __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

Якщо когось цікавить - ця рекурсивна функція повертає вкладену структуру словників. Ключі - це file systemімена (каталогів та файлів), значення - або:

  • під словники для каталогів
  • рядки для файлів (див. file_token)

У цьому прикладі рядки, що позначають файли, порожні. Вони також можуть бути, наприклад, заданим вмістом файлу або його власником або привілеями або будь-яким об'єктом, відмінним від диктату. Якщо це не словник, його можна легко відрізнити від "типу каталогу" в подальших операціях.

Маючи таке дерево у файловій системі:

# 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

Результатом буде:

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

Якщо вам це подобається, я вже створив пакет (python 2 & 3) з цими матеріалами (і приємним pyfakefsпомічником): https://pypi.org/project/fsforge/


4

Зверху на відповідь dhobbs вище ( https://stackoverflow.com/a/9728478/624597 ), ось додаткова функціональність зберігання результатів у файл (я особисто використовую його для копіювання та вставки у FreeMind, щоб мати гарний огляд структура, тому я використовував вкладки замість пробілів для відступу):

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

ця відповідь справді допомогла, дякую
prex

2

Ви можете виконати команду 'tree' оболонки Linux.

Установка:

   ~$sudo apt install tree

Використання в python

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

Приклад:

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

Це дає вам більш чисту структуру та візуально більш всеосяжну та просту у введенні.


Це не дуже портативне рішення, оскільки це не вдається для Windows + покладається на додаткову програму
oglop

2

Це рішення працюватиме лише в тому випадку, якщо ви treeвстановлені у вашій системі. Однак я залишаю це рішення тут лише на випадок, якщо це допоможе комусь іншому.

Ви можете сказати дереву виводити структуру дерева у вигляді XML ( tree -X) або JSON ( tree -J). Зрозуміло, JSON може бути розібраний безпосередньо з python, а XML легко зчитується lxml.

Як приклад наведена наступна структура каталогу:

[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 (можливо)

import os
def file_writer (текст):
    з відкритими ("folder_structure.txt", "a") як f_output:
        f_output.write (текст)
def list_files (стартовий шлях):


    для root, dirs, файли в os.walk (startpath):
        level = root.replace (стартовий шлях, '') .count (os.sep)
        відступ = '\ t' * 1 * (рівень)
        output_string = '{} {} / \ n'.формат (відступ, ім'я os.path.base (корінь))
        file_writer (output_string)
        subindent = '\ t' * 1 * (рівень + 1)
        output_string = '% s% s \ n'% (підрядник, [f для f у файлах])
        file_writer (''. join (output_string))


list_files ("/")

Результати тесту на скріншоті нижче:

введіть тут опис зображення



0

Для тих, хто ще шукає відповіді. Ось рекурсивний підхід для отримання шляхів у словнику.

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 чудова!

а просто змінити, щоб легко отримати інформацію про рівень

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)

і вихід, як

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

ви можете отримати рівень за |рахунком!

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.