我已经通过删除目录树中的文件进行了大量清理。我现在想删除空目录,因为现在有很多“几乎为空”的目录:它们仅包含一个隐藏.directory
文件。这样做的find -empty
结果是……空的。我不想删除包含其他文件的目录的点文件。
我可以想到一些复杂的 bash 脚本find
,但我想不出一个简单的方法来实现它...例如这里的解决方案(Linux:删除只有一个文件而没有子目录的所有目录)找不到点文件。
澄清:A.directory
是 KDE(?)创建的隐藏文本文件dolphin
,包含有关如何显示目录内容的信息,例如缩略图、文件列表或仅仅是它们的图标等……当文件被删除时,该.directory
文件会保留下来,但现在基本上没用了。
你提到了
find -empty
,所以你的find
可能是 GNUfind
。在这个答案中,我将使用 GNU 的几个不可移植功能find
。请先在可扩展目录中测试我的解决方案。解决方案是:
它的工作原理如下:
因为
-delete
暗示-depth
,该命令只有在处理完目录中的所有内容后才会处理目录。这很好,因为我们确实希望它先处理并可能删除更深的子目录,因此当它到达父目录时,它有可能刚刚变为空或几乎为空。该命令作用于目录类型的文件(
-type d
)。如果当前考虑的目录是空的,该命令将尝试删除它(
-empty -delete
)。否则(即如果目录不为空),将执行一段 shell 代码。坦白地说,如果目录为空且删除失败,也会执行该代码;但在这种情况下,该代码片段应该是无害的,所以没问题。
shell 代码使用
&&
,因此只有当前一步成功时,才会执行下一步。步骤如下:test -f …
)。-mindepth 1 -maxdepth 1
。如果内部输出find
为空,则将grep -q .
以非零退出状态退出,因此! grep …
将返回成功...rm
就会执行删除“特殊”文件的操作。只有
rm
成功了,-exec
测试才会被认为是目录的真实测试,并且-delete
会尝试最后一次。-print
-delete
将打印成功(第一个或第二个)的目录的路径名。笔记:
-delete
也没有删除,尽管它正式成功了。.
-name
采用模式。一般来说,如果“特殊”名称包含*
,?
或者[
,那么您需要调整代码。.directory
在这件事上是安全的。考虑到某些答案的复杂性,我认为 Perl 或 Python 是遍历目录树、获取目录条目列表以及检查它是否完全等于包含 1 个元素的列表
.directory
(并且它是一个常规文件)的正确工具。为每个子目录使用
find
fork/exec 复杂sh -c
命令似乎是一种浪费,我的眼睛都快要看不懂 Kamil 的回答中的逻辑了。假设整个树的递归目录列表很容易放入系统的 RAM 中,那么简单的工具就是最佳选择。Perl 具有
File::Find
深度优先递归功能,这很好,但它希望在每个目录条目上调用回调函数。因此,如果您想要一个目录列表,您必须在此基础上自己完成。虽然不是特别好,但也不理想,所以我研究了 Python。Python 的目录遍历标准库函数是
os.walk
,它是深度优先的。但有趣的是,它生成一个迭代器root, dirs, files
(我复制的使用示例),其中后两个是目录内容的列表root
,分为目录和非目录文件。这正是我们想要的;或者在深度优先搜索中。对于您的用例,删除仅包含其他目录的目录中的文件可能没问题
.directory
? 如果是这样,我们可以使用 Python 执行此操作,然后使用find -depth -type d -empty -delete
(或-print -delete
查看我们将删除哪些目录)。测试设置:
使用方法,调试打印版本:
实际用法:运行 Python 脚本删除
.directory
文件,然后find ... -delete
深度优先删除空目录。find
如果我想构建更可重用的解决方案,我可以在循环后使用 Python exec。剩下的就只有
foo/a.txt
和(当然foo/.directory
还有目录本身)。foo
限制:即使非空,
foo/bar/.directory
也会被删除foo/bar/baz
,但最终并没有被删除。 如果不用 Python 进行深度优先搜索,或者回到 Perl 并使用它自己File::Find
列出目录,我认为没有简单的解决方案。我只了解一点点 Python,但这仍然很容易实现,并且我依靠标准库来完成繁重的工作,所以希望它应该是强大的。
我不确定我是否完全理解了您的意思,但是这能满足您的要求吗?
然后运行:
然后会产生: