灵活的递归目录迭代器:scandir满足glob(“*”,recursive=true)
scantree的Python项目详细描述
扫描树
递归目录迭代器支持:
- 包括通配符路径匹配的柔性过滤< /LI>
- 文件树的内存表示(用于重复访问)
- 有效地访问目录项属性(
posix.DirEntry
接口),扩展了相对于递归根目录的实际路径和路径 - 循环符号链的检测和处理
安装
pip install scantree
用法
完整文档请参见源代码,下面是一些通用示例。
获取匹配的文件路径:
fromscantreeimportscantree,RecursionFiltertree=scantree('/path/to/dir',RecursionFilter(match=['*.txt']))print([path.relativeforpathintree.filepaths()])print([path.realforpathintree.filepaths()])
['d1/d2/file3.txt', 'd1/file2.txt', 'file1.txt']
['/path/to/other_dir/file3.txt', '/path/to/dir/d1/file2.txt', '/path/to/dir/file1.txt']
访问文件树中目录项的元数据:
d2=tree.directories[0].directories[0]print(type(d2))print(d2.path.absolute)print(d2.path.real)print(d2.path.is_symlink())print(d2.files[0].relative)
scantree._node.DirNode
/path/to/dir/d1/d2
/path/to/other_dir
True
d1/d2/file3.txt
按在树上操作聚合信息:
hello_count=tree.apply(file_apply=lambdapath:sum([w.lower()=='hello'forwinpath.as_pathlib().read_text().split()]),dir_apply=lambdadir_:sum(dir_.entries),)print(hello_count)
3
hello_count_tree=tree.apply(file_apply=lambdapath:{'name':path.name,'count':sum([w.lower()=='hello'forwinpath.as_pathlib().read_text().split()])},dir_apply=lambdadir_:{'name':dir_.path.name,'count':sum(e['count']foreindir_.entries),'sub_counts':[eforeindir_.entries]},)frompprintimportpprintpprint(hello_count_tree)
{'count': 3,
'name': 'dir',
'sub_counts': [{'count': 2, 'name': 'file1.txt'},
{'count': 1,
'name': 'd1',
'sub_counts': [{'count': 1, 'name': 'file2.txt'},
{'count': 0,
'name': 'd2',
'sub_counts': [{'count': 0,
'name': 'file3.txt'}]}]}]}
柔性过滤:
without_hidden_files=scantree('.',RecursionFilter(match=['*','!.*']))without_palindrome_linked_dirs=scantree('.',lambdapaths:[pforpinpathsifnot(p.is_dir()andp.is_symlink()andp.name==p.name[::-1])])
比较:
tree=scandir('path/to/dir')# make some operations on filesystem, make sure file tree is the same:asserttree==scandir('path/to/dir')# tree contains absolute/real path info:importshutilshutil.copytree('path/to/dir','path/to/other_dir')new_tree=scandir('path/to/other_dir')asserttree!=new_treeassert([p.relativeforpintree.leafpaths()]==[p.relativeforpinnew_tree.leafpaths()])
检查符号链接:
fromscantreeimportCyclicLinkedDirfile_links=[]dir_links=[]cyclic_links=[]deffile_apply(path):ifpath.is_symlink():file_links.append(path)defdir_apply(dir_node):ifdir_node.path.is_symlink():dir_links.append(dir_node.path)ifisinstance(dir_node,CyclicLinkedDir):cyclic_links.append((dir_node.path,dir_node.target_path))scantree('.',file_apply=file_apply,dir_apply=dir_apply)