search
LoginSignup
38

More than 1 year has passed since last update.

posted at

updated at

Pythonでファイルのツリー構造を出力する

概要

コマンドのtreeみたいな感じで、Python上でファイルやディレクトリのツリー構造をいい感じに出力する関数を作ったのでメモ。

結論

下記の関数にツリーで表示したいディレクトリのパスを与えれば良い。Mac用に実装しているので、パスがスラッシュで区切られないような場合は非対応。

import pathlib
import glob
import os

def tree(path, layer=0, is_last=False, indent_current=' '):
    if not pathlib.Path(path).is_absolute():
        path = str(pathlib.Path(path).resolve())

    # カレントディレクトリの表示
    current = path.split('/')[::-1][0]
    if layer == 0:
        print('<'+current+'>')
    else:
        branch = '└' if is_last else '├'
        print('{indent}{branch}<{dirname}>'.format(indent=indent_current, branch=branch, dirname=current))

    # 下の階層のパスを取得
    paths = [p for p in glob.glob(path+'/*') if os.path.isdir(p) or os.path.isfile(p)]
    def is_last_path(i):
        return i == len(paths)-1

    # 再帰的に表示
    for i, p in enumerate(paths):

        indent_lower = indent_current
        if layer != 0:
            indent_lower += '  ' if is_last else '│ '

        if os.path.isfile(p):
            branch = '└' if is_last_path(i) else '├'
            print('{indent}{branch}{filename}'.format(indent=indent_lower, branch=branch, filename=p.split('/')[::-1][0]))
        if os.path.isdir(p):
            tree(p, layer=layer+1, is_last=is_last_path(i), indent_current=indent_lower)

例えば、Testというディレクトリが以下のように構成されている場合を考える。

  • Test
    • Test_01
      • bbbbb.txt
      • ccccc.txt
    • Test_02
    • Test_03
    • aaaaa.txt

この時treeを実行するとこんな感じ。

tree('/hogehoge/Test')
出力結果
<Test>
 ├<Test_01>
 │ ├ccccc.txt
 │ └bbbbb.txt
 ├<Test_02>
 ├<Test_03>
 └aaaaa.txt

相対パスで指定しても結果は同じ。

tree('./') # /hogehoge/Test で実行
出力結果
<Test>
 ├<Test_01>
 │ ├ccccc.txt
 │ └bbbbb.txt
 ├<Test_02>
 ├<Test_03>
 └aaaaa.txt

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
38