Hendry
Hendry

Reputation: 900

Print out the whole directory tree

The code I have now:

import os

Tree = {}
Tree = os.listdir('Dir')
>>> print(Tree)
['New Folder', 'Textfile1.txt', 'Textfile2.txt']

That doesn't print out the files in the subdirectories. (New Folder is a subdirectory).

My question is, how can I output all the files in the directory and the files in subdirectories?

Upvotes: 4

Views: 15609

Answers (5)

Peter Prescott
Peter Prescott

Reputation: 908

If you want to limit your printed tree to some given depth, probably because you have a lot of nested folders, then you don't want to use os.walk. Instead you want to stop iterating through the nested folders as soon as you've reached your desired depth.

from typing import Union, Optional
from pathlib import Path

def ptree(startpath: Union[str, Path], 
          max_depth:int = 1, 
          quick_glance: Optional[int] = None, 
          _current_depth:int = 0) -> None:
  """
  Recursively print directory tree up to a given `max_depth`, specifying if you
  like a limited number of files and dirs to include in a `quick_glance`.
  
  Parameters
  ----------
  startpath: Union[str, Path]
    The filepath at which to start.
  max_depth: int
    The maximum depth of nested directories to explore.
  quick_glance: Optional[int]
    If specified, limits exploration to the first however-many files and dirs.
  _current_depth: int
    So that we can track our depth as we call the function recursively.
  """
  
  if _current_depth==0:
    print(startpath)
  else:
    print(f'{"--"*_current_depth}{[d for d in startpath.split(os.sep) if d][-1]}')
  _current_depth += 1
  
  if _current_depth > max_depth:
    return None
  else:
    ls = os.listdir(startpath)
    files = [f for f in ls if os.path.isfile(os.path.join(startpath,f))]
    dirs = [d for d in ls if os.path.isdir(os.path.join(startpath,d))]
    
    if quick_glance:
      files = files[:quick_glance]
      dirs = dirs[:quick_glance]

    [print(f'{".."*_current_depth}{f}') for f in files]

    [ptree(os.path.join(startpath, d), max_depth, quick_glance, _current_depth)
       for d in dirs]
    
    return None

Upvotes: 0

Arnon Sela
Arnon Sela

Reputation: 31

Here is yet another version appropriate for python3

Example output:

pyvarstar/
|-- .bashrc
|-- README
|-- vstars -> versions/vstars_20170804/ 
|-- versions/ 
|   |-- vstars_20170804/ 
|   |   |-- lib/
|   |   |   |-- vstars/ 
|   |   |-- bin/ 
|   |   |   |-- getcoords
|   |   |   |-- find_burst

The code:

def realname(path, root=None):
    if root is not None:
        path=os.path.join(root, path)
    result=os.path.basename(path)
    if os.path.islink(path):
        realpath=os.readlink(path)
        result= '%s -> %s' % (os.path.basename(path), realpath)
    return result

def ptree(startpath, depth=-1):
    prefix=0
    if startpath != '/':
        if startpath.endswith('/'): startpath=startpath[:-1]
        prefix=len(startpath)
    for root, dirs, files in os.walk(startpath):
        level = root[prefix:].count(os.sep)
        if depth >-1 and level > depth: continue
        indent=subindent =''
        if level > 0:
            indent = '|   ' * (level-1) + '|-- '
        subindent = '|   ' * (level) + '|-- '
        print('{}{}/'.format(indent, realname(root)))
        # print dir only if symbolic link; otherwise, will be printed as root
        for d in dirs:
            if os.path.islink(os.path.join(root, d)):
                print('{}{}'.format(subindent, realname(d, root=root)))
        for f in files:
            print('{}{}'.format(subindent, realname(f, root=root)))

Upvotes: 3

Noctis Skytower
Noctis Skytower

Reputation: 22011

From recipe 577091 on the Python Cookbook, you might use or learn from the TREE Emulator there.

import sys, os

FILES = False

def main():
    if len(sys.argv) > 2 and sys.argv[2].upper() == '/F':
        global FILES; FILES = True
    try:
        tree(sys.argv[1])
    except:
        print('Usage: {} <directory>'.format(os.path.basename(sys.argv[0])))

def tree(path):
    path = os.path.abspath(path)
    dirs, files = listdir(path)[:2]
    print(path)
    walk(path, dirs, files)
    if not dirs:
        print('No subfolders exist')

def walk(root, dirs, files, prefix=''):
    if FILES and files:
        file_prefix = prefix + ('|' if dirs else ' ') + '   '
        for name in files:
            print(file_prefix + name)
        print(file_prefix)
    dir_prefix, walk_prefix = prefix + '+---', prefix + '|   '
    for pos, neg, name in enumerate2(dirs):
        if neg == -1:
            dir_prefix, walk_prefix = prefix + '\\---', prefix + '    '
        print(dir_prefix + name)
        path = os.path.join(root, name)
        try:
            dirs, files = listdir(path)[:2]
        except:
            pass
        else:
            walk(path, dirs, files, walk_prefix)

def listdir(path):
    dirs, files, links = [], [], []
    for name in os.listdir(path):
        path_name = os.path.join(path, name)
        if os.path.isdir(path_name):
            dirs.append(name)
        elif os.path.isfile(path_name):
            files.append(name)
        elif os.path.islink(path_name):
            links.append(name)
    return dirs, files, links

def enumerate2(sequence):
    length = len(sequence)
    for count, value in enumerate(sequence):
        yield count, count - length, value

if __name__ == '__main__':
    main()

Upvotes: 3

zhangyangyu
zhangyangyu

Reputation: 8610

import os 
def Test1(rootDir): 
    list_dirs = os.walk(rootDir) 
    for root, dirs, files in list_dirs: 
        for d in dirs: 
            print os.path.join(root, d)      
        for f in files: 
            print os.path.join(root, f) 

OR:

import os 
def Test2(rootDir): 
    for lists in os.listdir(rootDir): 
        path = os.path.join(rootDir, lists) 
        print path 
        if os.path.isdir(path): 
            Test2(path)

For the test file tree:

E:\TEST 
│--A 
│  │--A-A 
│  │  │--A-A-A.txt 
│  │--A-B.txt 
│  │--A-C 
│  │  │--A-B-A.txt 
│  │--A-D.txt 
│--B.txt 
│--C 
│  │--C-A.txt 
│  │--C-B.txt 
│--D.txt 
│--E 

Running the following code:

Test1('E:\TEST') 
print '=======================================' 
Test2('E:\TEST') 

You can see there are difference between the results:

>>>  
E:\TEST\A 
E:\TEST\C 
E:\TEST\E 
E:\TEST\B.txt 
E:\TEST\D.txt 
E:\TEST\A\A-A 
E:\TEST\A\A-C 
E:\TEST\A\A-B.txt 
E:\TEST\A\A-D.txt 
E:\TEST\A\A-A\A-A-A.txt 
E:\TEST\A\A-C\A-B-A.txt 
E:\TEST\C\C-A.txt 
E:\TEST\C\C-B.txt 
======================================= 
E:\TEST\A 
E:\TEST\A\A-A 
E:\TEST\A\A-A\A-A-A.txt 
E:\TEST\A\A-B.txt 
E:\TEST\A\A-C 
E:\TEST\A\A-C\A-B-A.txt 
E:\TEST\A\A-D.txt 
E:\TEST\B.txt 
E:\TEST\C 
E:\TEST\C\C-A.txt 
E:\TEST\C\C-B.txt 
E:\TEST\D.txt 
E:\TEST\E 
>>> 

To save them in a list:

import os 
files = []
def Test1(rootDir):
    files.append(rootDir)
    list_dirs = os.walk(rootDir) 
    for root, dirs, files in list_dirs: 
        for d in dirs: 
            files.append(os.path.join(root, d))      
        for f in files: 
            files.append(os.path.join(root, f))

import os 
files = [rootDir]
def Test2(rootDir):
    for lists in os.listdir(rootDir): 
        path = os.path.join(rootDir, lists) 
        files.append(path) 
        if os.path.isdir(path): 
            Test2(path)

Upvotes: 6

Ashwini Chaudhary
Ashwini Chaudhary

Reputation: 251001

Use os.walk:

>>> import os
>>> print(os.walk.__doc__)
Directory tree generator.

    For each directory in the directory tree rooted at top (including top
    itself, but excluding '.' and '..'), yields a 3-tuple
    ...

Upvotes: 1

Related Questions