列出所有不包含子目录的目录

4
我有一个解决方案可以回答我的问题。
find . -type d -exec sh -c 'test $(find "$0" -maxdepth 1 -type d | wc -l) -eq 1' {} \; -print

我想知道是否有更好(更快)的方法来完成这个任务。我不太喜欢使用“查找”又进行一次查找的过程。


2
也许这个链接可以给你一些灵感:https://dev59.com/aHI_5IYBdhLWcg3wAd82 - epsilon
2个回答

4

man find 会列出一个选项:

   -links n
          File has n links.

你正在寻找只包含两个链接(即 . 和它的名称)的目录。以下将返回没有子目录的目录:
find . -type d -links 2

在正常的Unix文件系统上,每个目录至少有两个硬链接:它的名称和它的.(父目录)入口。此外,它的子目录(如果有)每个都有一个链接到该目录的..入口。


在 NTFS 分区上的目录运行 find . -type d -links 2 命令的输出为空。对于 Ext3 文件系统,该解决方案有效。 - boxdot
1
@finite 你说得对。然而,它在本地文件系统上运行良好,这是假设的。 - devnull
实际上这个代码确实给出了正确的结果,但原因并不是解释的那样。任何目录至少有两个硬链接(即目录本身和“.”),任何子目录都会增加1个计数(即子目录内的“..”)。 - toro2k
@toro2k:创建一个只有一个文件的子目录,这个命令不会列出该子目录。 - anubhava
1
嗯... mkdir -p foo/bar/baz; touch foo/bar/baz/something; find foo -type d -links 2 返回 foo/bar/baz - devnull
@devnull:执行mkdir abc; touch abc/pqr.txt,然后这个find命令就不会在输出中列出abc - anubhava

1

只需稍加编码,以下命令也可以正常工作:

find . -type d|awk 'NR>1{a[c++]=$0; t=t $0 SUBSEP} END{for (i in a) {if (index(t, a[i] "/") > 0) delete a[i]} for (i in a) print a[i]}'

使其更易读:
find . -type d | awk 'NR > 1 {
   a[c++]=$0;
   t=t $0 SUBSEP
}
END {
   for (i in a) {
      if (index(t, a[i] "/") > 0)
         delete a[i]}
   for (i in a)
      print a[i]
}'

在一个大目录中,这个基于awk的命令看起来可能需要更多的编码,但是相比问题中嵌入的find | wc解决方案,它应该运行得更快。
性能测试:
我在一个包含15k+嵌套子目录的目录上运行了它,发现这个awk命令比OP的find | wc命令快得多(速度提高了250-300%)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接