tree这个命令的作用是列出文件树,是windows一个自带指令,linux也能安装这个命令。
他的运行效果是这样的:
我们尝试用python来复现这个指令的功能。
我们首先来分析一下这个指令到底都打印出了什么些东西:
- 第一行是当前目录的路径
- 从第二行开始如果不是最后一个元素就打印出一个’├─’,并且后面如果是其他目录的后就打印’│ ‘。如果是最后一个元素就是 ‘└─’,并且后面如果是其他目录的话就打印空白。
- 如果这个元素是目录的话就打印出目录名,然后重复上面的步骤(递归)
- 如果这个元素是文件的话就仅仅打印出这个文件名。
因为需要用到目录相关的操作,我们引用os库:
import os
然后我们定义函数用于枚举给出目录的所有文件:
def tree(top='.'):
components = os.listdir(top)
components_num = len(components)
for i, component in enumerate(components, start=1):
component_path = os.path.join(top, component)
这里components就是该目录下的所有元素。components_num就是元素的数量,用于判断当前元素是否是最后一个元素。在循环内的component_path用于稍后判断这个元素是文件还是目录。
在循环内我们通过这个元素是否是最后一个元素判断元素前的符号应该打印什么:
if i == components_num:
prefix = ('└─', ' ')
else:
prefix = ('├─', '│ ')
然后我们先生成当前元素应该打印的东西:
yield f'{prefix[0]}{component}'
用生成器而不是直接字符串拼接然后打印的原因是如果是一个目录的话就得等这个目录走完才能打印,如果用生成器的话每行都可以直接打印。
如果这个元素是一个目录的话,我们调用自身,并把生成的东西加上竖线再生成到上一层:
if os.path.isdir(component_path):
for line in tree(component_path):
yield f'{prefix[1]}{line}'
最后我们调用这个函数:
if __name__ == '__main__':
for line in tree():
print(line)
所以最后的程序长这样:
import os
import sys
def tree(top='.'):
components = os.listdir(top)
components_num = len(components)
for i, component in enumerate(components, start=1):
component_path = os.path.join(top, component)
if i == components_num:
prefix = ('└─', ' ')
else:
prefix = ('├─', '│ ')
yield f'{prefix[0]}{component}'
if os.path.isdir(component_path):
for line in tree(component_path):
yield f'{prefix[1]}{line}'
if __name__ == '__main__':
if len(sys.argv) > 1:
path = sys.argv[1]
else:
path = '.'
for line in tree(path):
print(line)
我们调用这个脚本: