파이썬에서 디렉토리 트리 구조를 나열합니까?


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

파이썬에서 이것을 가장 잘 달성하는 방법은 무엇입니까?

답변:


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
이것은 아주 잘 작동했습니다. 감사합니다. 대부분은 알겠지만, 파이썬을 처음 접하는 사람들의 이익을 위해-마지막에 함수를 호출해야한다는 점에 유의하십시오 (윈도우 가정). 따라서 마지막에 list_files ( "D : \\ ")
라훌

1
python3에서 잘 작동했습니다. 그러나 python2에서는 ValueError: zero length field name in format던져집니다.
nipunasudha

3
루트 내에서 startpath가 반복되면 각 항목을 대체하지 않습니까? 로 변경하면 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 가 발생 합니다.
  • 나무는 느리게 평가됩니다. 정말 넓은 폴더 트리 에서 잘 작동해야합니다 . 그러나 주어진 폴더의 직계 자식은 느리게 평가되지 않습니다.

편집하다:

  • 보너스 추가! 필터링 경로에 대한 기준 콜백.

좋은 도구, 폴더 이름을 제외하기 위해 기준을 사용하는 방법에 대한 간단한 예가 있습니까?
Matt-Mac-Muffin

이것이 바로 제가 찾던 것입니다. 정말 고맙습니다!
dheinz

24

들여 쓰기가없는 솔루션 :

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

os.walk는 이미 찾고있는 하향식 깊이 우선 걷기를 수행합니다.

dirs 목록을 무시하면 언급 한 중복을 방지 할 수 있습니다.


2
파이썬은 말합니다 :NameError: name 'path' is not defined
프란체스코 만토바니

1
@FrancescoMantovani "경로"인쇄 할 디렉토리를 포함하는 변수, 즉 R은 "C : \ 사용자 \ 사용자 이름 \ 문서 \ 경로"
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.

나는 또한 그런 종류의 출력에 접근하는 다른 답변을 여기에서 볼 수 있지만 더 간단하고 현대적인 코드와 느리게 평가하는 접근 방식으로 더 잘할 수 있다고 생각합니다.

Python의 트리

먼저 다음과 같은 예를 사용하겠습니다.

  • Python 3 Path객체를 사용 합니다.
  • (생성기 함수를 만드는) yieldyield 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재귀 적 globbing 에도 사용할 수 있지만 다시 작성해야합니다. 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 하십시오 . 적절한 공백 은 이 링크 를 참조하십시오 .
Steven C. Howell

이것이 바로 제 코드에 필요한 것이었고 새로운 파이썬 트릭을 가르쳐주었습니다! 내가 주목할 것은 True 인 contents경우 필터링해야한다는 것 limit_to_directories입니다. 그렇지 않으면 폴더에 마지막 파일에 대한 디렉토리가 없으면 트리가 올바르게 그려지지 않습니다. if limit_to_directories: contents = [path for path in contents if path.is_dir()]
hennign

@hennign 감사합니다. 답변이 업데이트되었습니다. 피드백에 감사드립니다!
Aaron Hall

파이썬은 모두 list(dir_path.iterdir())적절하게 정렬 된 디렉터리 구조의 하향식 트리 를 반환하는 것을 전제 로합니다. 내가 볼 수없는 그런 보장 에서 iterdir에 대한 API를 () . iterdir()주문 방법에 대한 참조 를 제공하거나 원하는 주문을 제공 할 수 있습니다.
ingyhere

당신이 아이디어를 어디서 얻었는지 잘 모르겠어요 @ingyhere - 그것을 사용하는 것 os.listdir()기본적으로 - 순서 보장하지 않습니다 : '.' "목록은 임의의 순서에, 그리고 특별 항목을 포함하지 않습니다 그리고 '..'이 디렉토리에 있더라도. "
Aaron Hall

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 2015-09-17

3
당신의 느낌이 맞습니다, @ jason-heine. 받아 들여진 대답은 충분하지만 어떤 사람들은이 보풀을 어떻게하는지 물었고 나는 그들에게 무언가를주고 싶었습니다. 이걸보고 싶지 않다면 반대표를 던지거나 내 대답을보고하면 아프지 않을 것이라고 생각했지만 틀릴 수도 있습니다.
Rubén Cabrera 2015

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-*-#-*-코딩 : utf-8-*-

# tree.py# tree.py
##
# Doug Dahms 작성# Doug Dahms 작성
##
# 명령 줄에 지정된 경로에 대한 트리 구조를 인쇄합니다.# 명령 줄에 지정된 경로에 대한 트리 구조를 인쇄합니다.

os import listdir, sep에서에서 운영 체제 수입 은 listDir , 9월
os.path에서 가져 오기 abspath, basename, isdir에서 운영 체제 . 경로 가져 오기 abspath , basename , isdir
sys import argv에서에서 SYS 수입 ARGV

def tree (dir, padding, print_files = False, isLast = False, isFirst = False) :def 트리 ( dir , padding , print_files = False , isLast = False , isFirst = False ) :
    isFirst 인 경우 :isFirst 인 경우 :
        print padding.decode ( 'utf8') [:-1] .encode ( 'utf8') + dir인쇄 패딩 . 디코드 ( 'utf8' ) [: -1 ]. 인코딩 ( 'utf8' ) + dir 
    그밖에:그렇지 않으면 :
        isLast 인 경우 :isLast 인 경우 :
            print padding.decode ( 'utf8') [:-1] .encode ( 'utf8') + '└──'+ basename (abspath (dir))인쇄 패딩 . 디코드 ( 'utf8' ) [: -1 ]. encode ( 'utf8' ) + '└──' + basename ( abspath ( dir ))   
        그밖에:그렇지 않으면 :
            print padding.decode ( 'utf8') [:-1] .encode ( 'utf8') + '├──'+ basename (abspath (dir))인쇄 패딩 . 디코드 ( 'utf8' ) [: -1 ]. encode ( 'utf8' ) + '├──' + basename ( abspath ( dir ))   
    파일 = []= [] 
    print_files 인 경우 :print_files 인 경우 :
        파일 = listdir (dir)= listdir ( dir )
    그밖에:그렇지 않으면 :
        files = [x for x in listdir (dir) if isdir (dir + sep + x)]= [ x for x in listdir ( dir ) if isdir ( dir + sep + x )]  
    isFirst가 아닌 경우 :isFirst 아닌 경우 : 
        padding = padding + ''= 패딩 + '' 
    files = sorted (files, key = lambda s : s.lower ())= 정렬 됨 ( 파일 , = 람다 s : s . 더 낮은 ())
    개수 = 0= 0 
    마지막 = len (파일)-1= ( 파일 ) - 1  
    i의 경우 enumerate (files)의 파일 :에 대한 , 파일 열거 ( 파일 ) :
        카운트 + = 1+ = 1 
        경로 = dir + sep + 파일= dir + sep + 파일
        isLast = i == 마지막= 나는 == 마지막
        isdir (경로) :경우 ISDIR ( 경로 ) :
            개수 == len (파일) :만약 카운트 == ( 파일 ) :
                isFirst 인 경우 :if isFirst:
                    트리 (경로, 패딩, print_files, isLast, False)(path, padding, print_files, isLast, False)
                그밖에:else:
                    트리 (경로, 패딩 + '', print_files, isLast, False)(path, padding + ' ', print_files, isLast, False)
            그밖에:else:
                tree (경로, 패딩 + '│', print_files, isLast, False)(path, padding + '│', print_files, isLast, False)
        그밖에:else:
            isLast 인 경우 :if isLast:
                print padding + '└──'+ 파일print padding + '└── ' + file
            그밖에:else:
                print padding + '├──'+ 파일print padding + '├── ' + file

def usage () :def usage():
    return '' '사용법 : % s [-f] return '''Usage: %s [-f] 
지정된 경로의 트리 구조를 인쇄합니다.
옵션 :
-f 파일 및 디렉토리 인쇄
프로세스 경로 '' '% basename (argv [0]) % basename(argv[0])

def main () :def main():
    len (argv) == 1 :if len(argv) == 1:
        인쇄 사용 ()print usage()
    elif len (argv) == 2 :elif len(argv) == 2:
        # 디렉토리 만 인쇄# print just directories
        경로 = argv [1]= argv[1]
        isdir (경로) :if isdir(path):
            트리 (경로, '', False, False, True)(path, '', False, False, True)
        그밖에:else:
            print '오류 : \'+ 경로 + '\'는 디렉토리가 아닙니다. 'print 'ERROR: \'' + path + '\' is not a directory'
    elif len (argv) == 3 및 argv [1] == '-f':elif len(argv) == 3 and argv[1] == '-f':
        # 인쇄 디렉토리 및 파일# print directories and files
        경로 = argv [2]= argv[2]
        isdir (경로) :if isdir(path):
            트리 (경로, '', True, False, True)(path, '', True, False, True)
        그밖에:else:
            print '오류 : \'+ 경로 + '\'는 디렉토리가 아닙니다. 'print 'ERROR: \'' + path + '\' is not a directory'
    그밖에:else:
        인쇄 사용 ()인쇄 사용량 ()

__name__ == '__main__'인 경우 :경우 __name__ == '__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)

이 예에서는 파일을 지정하는 문자열이 비어 있습니다. 또한 예를 들어 주어진 파일 내용이나 소유자 정보 또는 권한 또는 dict와 다른 객체가 될 수 있습니다. 사전이 아니면 추가 작업에서 "디렉토리 유형"과 쉽게 구별 할 수 있습니다.

파일 시스템에 이러한 트리가있는 경우 :

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

당신이 그것을 좋아한다면, 나는 이미이 물건 (그리고 멋진 pyfakefs도우미) 으로 패키지 (파이썬 2 & 3)를 만들었다 : 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

Linux 쉘의 '트리'명령을 실행할 수 있습니다.

설치:

   ~$sudo apt install tree

파이썬에서 사용

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

예:

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

이것은 더 깔끔한 구조를 제공하고 시각적으로 더 포괄적이고 입력하기 쉽습니다.


은 Windows + 추가 프로그램에 의존 실패로 이것은 매우 휴대용 해결책이 아니다
oglop

2

이 솔루션은 tree시스템에 설치 한 경우에만 작동합니다 . 그러나 다른 사람을 도울 경우를 대비 하여이 솔루션을 여기에 남겨 둡니다.

트리 구조를 XML ( tree -X) 또는 JSON ( tree -J) 으로 출력하도록 tree에 지시 할 수 있습니다 . 물론 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보다 빠를 수도 있습니다 (아마도)

수입 OS
def file_writer (텍스트) :
    open ( "folder_structure.txt", "a")를 f_output으로 사용 :
        f_output.write (텍스트)
def list_files (startpath) :


    root, dirs, os.walk (startpath)의 파일 :
        레벨 = root.replace (startpath, '') .count (os.sep)
        들여 쓰기 = '\ t'* 1 * (레벨)
        output_string = '{} {} / \ n'.format (indent, os.path.basename (root))
        파일 _ 작성기 (출력 _ 문자열)
        하위 들여 쓰기 = '\ t'* 1 * (레벨 + 1)
        output_string = '% s % s \ n'% (subindent, [f for f in files])
        file_writer ( ''. join (출력 _ 문자열))


목록 _ 파일 ( "/")

아래 스크린 샷의 테스트 결과 :

여기에 이미지 설명 입력


0

다음과 같은 출력이있는 코드를 찾을 수 있습니다. 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

여전히 답을 찾고있는 사람들을 위해. 다음은 사전에서 경로를 가져 오는 재귀 적 접근 방식입니다.

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

|카운트로 레벨을 얻을 수 있습니다!

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.