我怎样才能找到每个空目录,比方说,在 /home/.../Desktop 上。因为我在 Solaris 上,所以无法使用该find . -empty -type d
命令。还有其他办法吗?
答案1
(我没有方便的 Solaris 机器,所以我正在使用联机帮助页,因此您可能需要在这里稍微使用一下语法。)
您可以利用这样一个事实:任何空目录的链接计数均为 2(仅目录名称本身 ,dir
加上它自己的dir/.
,链接到它);在 UNIX 中,除非将目录添加到(单个)目录条目或将目录条目添加到其中,否则(硬)链接到目录是非法的,因此这是一个不变量。 (基本上是1。)
Solaris 不支持该-empty
选项,但它做支持-links <n>
精确搜索事物的选项n链接。所以你想要的命令(我思考;见下文)是:
find /home/.../Desktop -type d -links 2 -print
顺便一提...
您对“递归”一词的使用有点含糊,因此请注意,这不会找到只包含空目录(或递归地)的目录。如果你想要的话,如果你想按顺序识别它们,问题就很简单删除它们。只需重复运行上面的命令,添加-exec rmdir {} \;
直到没有为止;每次运行它时,您都会将树的父级删除更深一层,因此不需要多次运行,除非您有一个非常深层目录树仅由空目录组成。 (取决于 Solaris 如何查找(1)有效,我想你也可以find . -type d -exec rmdir -p {};
只运行一次(该-p
选项告诉目录(1)它可以删除包含空目录的目录),但是因为它会尝试遍历已删除的目录,所以您会收到一堆错误消息,您可以忽略它们,它们与您可能关心的错误消息混合在一起,所以我' d 改为以迭代方式执行此操作。)
(请注意,该-depth
选项查找(1)在这里没有帮助,因为文件是统计()更新链接计数还为时过早。否则,你可以运行find -depth $dir -type d -links 2 -exec rmdir {} \;
,运行一次就足够了。)
如果你想识别两个都“本质上空”的目录和只包含空目录的目录(或递归地)而不删除它们,它更复杂。我认为单个命令行是可能的,但这将是一个野兽(我确信其他人稍后会尝试),至少不需要诉诸perl
疯狂sed
/awk
咒语。
但我要做的是将目录树复制到某个地方,比如说/tmp/树复制,然后运行命令
find /tmp/tree-copy -type d -links 2 -print -exec rmdir {} \; | tee -a /tmp/empty-dirlist
重复,直到不再产生输出。 (它tee -a
可以让您查看输出,还可以将其附加到文件中/tmp/空目录列表.)
然后,您需要/tmp/tree-copy
从文件的每一行中删除 或其他内容;
perl -i -lpe 's{^/tmp/tree-copy/}{}' /tmp/empty-dirlist
将适用于此,或者您可以使用文本编辑器。瞧!,空目录的列表,其中“空”被定义为“只包含目录”。 (如果您愿意,您也可以将perl
、 或sed
或其他内容放入管道中之前tee -a
。)
- 在一些人指出这一点之前,这对于文件系统来说不一定是正确的挂载点;某些操作系统上的文件系统管理器可以自由地将挂载点的链接计数用于自己的私人用途,因此您会经常看到挂载点目录,无论是否为空,其链接计数为
1
(在其他情况下对于目录是非法的),,2
或其他有意义但与其实际链接计数无关的东西。因此,如果您打算执行上述操作,您应该检查您是否可能会遍历挂载点,因为其中一个挂载点的链接计数有可能为 2,尽管可能性不大。
答案2
太棒了;
find . -type d -links 2 -exec sh -c '
is_empty () (
cd "$1"
set -- .[!.]* ; test -f "$1" && return 1
set -- ..?* ; test -f "$1" && return 1
set -- * ; test -f "$1" && return 1
return 0
)
is_empty "$0" ' {} \; -print
解释
-type d
和选项-links 2
一起工作,最初将结果限制为“叶”目录;即那些实际上是空的和/或仅包含文件的。为了只考虑空目录,我们需要更多的东西。
通常用于此目的的选项-empty
是非 POSIX 扩展。为了克服这个缺点,我借用了Rich 的 sh (POSIX shell) 技巧。这个-exec sh -c'...'
习语是我通常避免的,但我还没有找到更好的选择。