查找树中所有结束子目录

查找树中所有结束子目录

给出以下结构:

oz123@debian:~/ $ tree .
.
├── a
│   ├── a1
│   ├── a2
│   └── a3
├── a1
│   ├── a11
│   ├── a12
│   └── a31
├── b
│   └── b1
│       ├── b11
│       │   └── b21
│       │       └── b31
│       ├── b12
│       └── b3
└── c

16 directories, 0 files

如何找到所有的结束节点?

我找到了以下解决方案似乎是好的,但我必须证明没有测试用例会失败。

各州的帮助页面-links

您还可以使用“-links”搜索具有一定数量链接的文件。目录通常至少有两个硬链接;他们的 。条目是第二个。如果它们有子目录,则每个子目录还有一个名为 .. 的硬链接到其父目录。这 。和 .. 目录条目通常不会被搜索,除非它们在 find 命令行中被提及。

可能的解决方案:

oz123@debian:~/ $ find .  -type d  -links 2
./a/a2
./a/a3
./a/a1
./c
./a1/a31
./a1/a11
./a1/a12
./b/b1/b12
./b/b1/b3
./b/b1/b11/b21/b31
  • 任何人都可以提供更好的解决方案(不使用管道和 sed,这已经是高性能的......)
  • 它可以在任何文件系统上工作吗?

答案1

有一个更明显的选择-empty

find . -type d -empty

更新。好吧,你是对的,这种方式不适用于目录中的文件。

所以这里是一个固定的文件系统不可靠版本:

find dtest/ -type d -exec sh -c "if [ \$(find {} -maxdepth 1 -type d | wc -l) -eq 1 ]; then echo {} ; fi" \;

答案2

作为您自己的解决方案的补充-links,我想补充一点,它不适用于不遵循 Unix 目录链接约定的文件系统。从man find选项来看,-noleaf这些至少是 CD-ROM、MS-DOS 文件系统和 AFS 卷安装点。

作为参考,这个问题已经通过不同的解决方案进行了讨论,这些解决方案确实速度较慢,并且通常诉诸于 sed / awk 和类似的管道。

答案3

find . -type d -links 2适用于大多数文件系统,但并非全部。我认为除了知道哪些文件系统类型具有目录包含自身链接的属性之外,没有其他方法可以知道。 GNU find 会动态检测到这一点(如果它打印出有关“自动打开 find 的 -noleaf 选项”的信息,那么您就知道您的文件系统没有此属性)。大多数常见的文件系统类型都可以,但 FAT 或 btrfs 不行。

如果您想确定,您必须测试每个目录。执行此操作的一种方法是find再次调用每个子目录。

find . -type d ! -exec sh -c '
   find "$1/." ! -name . -type d -prune | grep -q "^"' sh {} \; -print

(使用 GNU find,您可以替换-prune-print -quit以使其更高效)。

另一种方法是对 的输出进行后处理find。对于find -depth,叶目录是不跟随其自身子目录的目录。

find . -depth -type d -print0 |
awk -v RS='\0' '
    substr(previous, 1, length($0) + 1) != $0 "/"
    { previous = $0 }
'

答案4

尝试以下解决方案(应与 Linux、Unix 和 OS X 兼容):

find . -type d -execdir sh -c 'test -z "$(find "{}" -mindepth 1 -type d)" && echo $PWD/{}' ';'

它的方法类似于紧急解决方案,但没有任何管道。

相关内容