已知目录树全文件、目录路径列表,不使用 IO 求空目录

2021-05-26 22:34:20 +08:00
 imn1
windows 路径
已知整个目录树所有子目录、文件的路径,str 列表
不考虑虚拟路径(软链硬链 mount/lnk 等)

不实际检查文件 IO,就是 is_dir()这些,单纯通过字符串之间关系,求出没有文件的空目录
有没有较快的方案?
2713 次点击
所在节点    Python
29 条回复
0ZXYDDu796nVCFxq
2021-05-27 15:01:26 +08:00
@imn1 双指针就可以了
假如输入数据是
/dir1/
/dir1/file1
/dir1/file2
/dir1/dir2/
/dir1/dir3/
/dir1/dir3/file3
/dir1/dir4/

规律就是 /dir1/dir2/, /dir1/dir4/ 都没有以这两个目录开头的文件
而 /dir1/, /dir1/dir3/,都可以找到匹配的文件

因为是有序的,所以不断滑动两个指针进行比较就行
3dwelcome
2021-05-27 15:17:27 +08:00
windows 上你用 dir /s 就可以了啊,这个命令会列出目录下所有<DIR>的路径。

然而,只有对于非空目录,才会有" D:\Users\Administrator 的目录"这种单行文本输出。

所以你找所有空目录,只要用全部<DIR>路径减去所有非空目录,剩下的就是空目录列表了。
3dwelcome
2021-05-27 15:19:50 +08:00
哦,dir /s 有点问题,就算空目录,还是会输出 0 File(s) 0 bytes,汗。
yazoox
2021-05-27 17:48:27 +08:00
@gstqc 双指针一般情况可以。但楼主如果是实际生产中的需求,可能不行。见#17 楼 @no1xsyzy 的情况,又指针就处理不了了。
yazoox
2021-05-27 17:50:17 +08:00
楼主,你代码已经写出来了?附言 4 就是 python 代码?我咋看不懂啊......
imn1
2021-05-27 18:00:38 +08:00
@yazoox #25
中间是个列表表达式,太长分了行而已,能用表达式我都不用 for 语句的,表达式也能执行函数,一样的

如果从上下行计算的话,需要一些移动函数(rolling),pandas 有,但暂时没见过单纯 python 实现的
O5oz6z3
2021-05-27 18:20:41 +08:00
没给出样例,问题描述也很含糊,目录树是按字符顺序还是路径关系排序、子目录是否以分隔符结尾、目录中只含有空目录是否也算作空目录……
但还是试着写了写,不知道行不行:
```python
from pathlib import Path
from itertools import zip_longest
# from pprint import pprint as pp

is_dir = lambda n: not Path(n).suffix
get_parent = lambda n: str(Path(n).parent)

# paths = ?
print('如果按路径关系排序')
result = [ k for k, v in zip_longest(paths, paths[1:], fillvalue='')
if is_dir(k) and not v.startswith(k) ]
# pp(result)

print('如果无序')
result = { k for k in paths if is_dir(k) }
for v in paths:
k = get_parent(v)
result.discard(k)
# pp(result)
```
(如果需要优化可以修改为迭代器,需要简化可以手动复制函数填充进表达式)
imn1
2021-05-27 18:53:49 +08:00
@O5oz6z3 #27
没有试,因为看到 pathlib
大目录树我个人不建议用 pathlib,至少目前是,我这个是个十万文件的大目录树,所以想寻求不使用 IO 的方法,如果只是小目录,我都懒得理,还不如省点时间做下一个事项

pathlib 逐个构建对象,即使是 purepath 也是消耗,已经有人在 python 提了 issue,等官方优化吧
pathlib 的优点是代码简单很多,递归树才一行,写 os.scandir 要好几行
如果要限定递归层级或者过滤,scandir 更加麻烦,pathlib 改改 glob 的字符参数就行了

PS: pathlib 递归树比 scandir 慢几倍

不过无序那部份我花时间研究一下
O5oz6z3
2021-05-27 19:00:17 +08:00
@imn1
1. 这份代码里面没有 IO 操作,使用 pathlib 只是为了方便字符串层面的路径操作。
2. pathlib 构建对象确实有性能问题,但这只是其中一种实现,lambda 代码可以用你写的 os...来代替。

顺便因为缩进问题,修改一下无序部分的代码:
```python
print('如果无序')
result = { k for k in paths if is_dir(k) }
temp = [ result.discard(get_parent(v)) for v in paths ]
# pp(result)
```
因为没法测试,所以不知道到底行不行得通。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/779438

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX