在树中找到所有末端子目录


11

给出以下结构:

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的情况下,它的性能很高...)
  • 它可以在任何文件系统上工作吗?

3
您将发现比-links 2技巧更出色的性能。它不会起作用 btrfs
斯特凡Chazelas

Answers:


3

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

作为参考,已经用不同的解决方案讨论了这个问题,这些解决方案的速度确实较慢,通常诉诸于sed / awk等。


3

还有一个更明显的选择-empty

find . -type d -empty

更新。好的,您说对了,这种方式将不适用于dirs中的文件。

因此,这是一个固定文件系统非依赖版本:

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

2
如果我理解这个问题,则最终目录可能包含文件。这不会打印那些目录,因为它们不会是“空的” ...
Stefan

@rush,子目录可以为空
Oz123 2013年

@ Oz123请检查我的更新,它应该足够快,但与您的方式相比要慢一些。

@rush,谢谢,但是我真的需要避免管道,它们会使事情变慢。
Oz123

1

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 }
'

0

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

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

这与紧急解决方案类似,但是没有任何管道。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.