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でこれを最高に達成する方法は?
書式設定でこれを行う関数は次のとおりです。
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))
インデントなしのソリューション:
for path, dirs, files in os.walk(given_path):
print path
for f in files:
print f
os.walkは既に、トップダウンで深さ優先の探索を行っています。
Dirsリストを無視すると、言及した重複が防止されます。
私は同じものを探してここに来て、私のためにドブスの答えを使いました。コミュニティに感謝する方法として、akshayが尋ねたように、ファイルに書き込むための引数をいくつか追加し、ファイルを表示することをオプションにしました。また、インデントをオプションの引数にして、変更できるようにしました。2が好きな人もいれば4が好きな人もいます。
異なるループを使用して、ファイルを表示していないループが各反復で必要かどうかをチェックしないようにしました。
ドブスの答えが私を助けてくれたので、それが他の誰かを助けることを願っています。どうもありがとう。
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
上記の回答に似ていますが、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
この素晴らしい投稿に基づいて
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 # #によって書かれたコマンドラインで指定されたパスのツリー構造を印刷します os import listdir、 sep from os.path import abspath、basename、isdir from sys import argv def tree(dir、padding、print_files = False、isLast = False、 isFirst = False): if isFirst: print padding.decode( 'utf8')[:-1] .encode( 'utf8')+ dir else: if isLast: print padding.decode( 'utf8')[:-1] .encode( 'utf8')+ '└──' + basename(abspath(dir)) else: print padding.decode( 'utf8')[:-1] .encode( 'utf8')+ '├──' + basename(abspath(dir)) files = [] if print_files: files = listdir(dir) else: files = [listdir(dir)のxのxはisdir(dir + sep + x)] is not isFirst: padding = padding + '' files = Sorted(files、key = lambda s:s.lower()) count = 0 last = len(files) -1 for i、列挙型ファイル(files): count + = 1 path = dir + sep + file 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、False) else: tree(path、padding + '│'、print_files、 isLast、False) else: if isLast: print padding + '└──' + file else: print padding + ' ├── '+ file def usage(): return' ''使用法:%s [-f] 指定されたパスのツリー構造を印刷します。 オプション: -fファイルとディレクトリを出力します PATHプロセスへのパス '' '%basename(argv [0]) def main (): if len(argv)== 1: print usage() Elif len(argv)== 2: #ディレクトリのみを印刷 path = argv [1] if isdir(path): tree(path、 ''、False、False、True) else: print 'エラー:\' '+パス+'\'はディレクトリではありません' Elif len(argv)== 3 and argv [1] == '-f': #ディレクトリとファイルの出力 path = argv [2] if isdir(path): tree(path、 ''、True、False、True) else : print 'エラー:\' '+パス+'\'はディレクトリではありません' else: print usage() if __ == '__main __': main()
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': {}
}
あなたがそれを好めば、私はすでにこのもの(そしてNice pyfakefs
ヘルパー)でパッケージ(python 2と3)を作成しました: https://pypi.org/project/fsforge/
上記の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(".")
Linux Shellの「tree」コマンドを実行できます。
インストール:
~$Sudo apt install tree
Pythonで使用する
>>> import os
>>> os.system('tree <desired path>')
例:
>>> os.system('tree ~/Desktop/myproject')
これにより、構造が簡潔になり、視覚的により包括的で入力しやすくなります。
このソリューションは、システムに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}
]
@ellockieよりも高速かもしれません(たぶん)
import os def file_writer(text): with open( "folder_structure.txt"、 "a")as f_output: f_output.write(text) def list_files(startpath): root、dirs、os.walk(startpath)内のファイル: level = root.replace (startpath、 '').count(os.sep) indent = '\ t' * 1 *(レベル) output_string = '{} {}/\ n'.format(indent 、os.path.basename(root)) file_writer(output_string) subindent = '\ t' * 1 *(level + 1) output_string = '%s%s\n '%(subindent、[f in f in files]) file_writer(' '。join(output_string)) list_files( "/" )
以下のスクリーンショットのテスト結果:
ここでは、次のような出力のコードを見つけることができます。 https://stackoverflow.com/a/56622847/66713
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
まだ答えを探している人のために。辞書のパスを取得する再帰的なアプローチを次に示します。
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}