我试图使用GNU find仅查找包含其他目录的目录,但可能包含或不包含常规文件。
到目前为止,我最好的猜测是:
find dir -type d \( -not -exec ls -dA ';' \)
但这只会给我一个很长的“。”列表。
谢谢!
如果你的文件系统符合 POSIX 标准(即每个子目录都有一个链接,父目录和自身也各有一个链接,因此如果没有子目录,则链接数为 2),则可以使用 -links
。
以下命令应该能满足你的需要:
find dir -type d -links 2
然而,在 Mac OS X 上似乎不起作用(如 @Piotr 所述)。这里是另一个版本,虽然速度较慢,但在 Mac OS X 上可以使用。它基于他的版本,对处理目录名称中的空格进行了更正:
find . -type d -exec sh -c '(ls -p "{}"|grep />/dev/null)||echo "{}"' \;
-links 2
也不行,第二个方案也不行,因为有一些目录的名称中带有$
符号,例如$RECYCLE.BIN
。但是在ext[234]分区上可以正常运行。 - mivkfind -exec
)的解决方法!它涉及两次使用sort
和awk
:find dir -type d | sort -r | awk 'a!~"^"$0{a=$0;print}' | sort
将find
命令的输出结果按照相反顺序排序。
使用awk
命令在当前行是前一行的前缀时省略行。
sort
它们(使其看起来像正常的find
输出)。对于某些晦涩的原因,@Sylvian的解决方案在我的mac os x上没有起作用。因此,我想出了一个更直接的解决方案。希望这能帮到某些人:
find . -type d -print0 | xargs -0 -IXXX sh -c '(ls -p XXX | grep / >/dev/null) || echo XXX' ;
解释:
ls -p
命令会在目录名后面加上 '/' 符号(ls -p XXX | grep / >/dev/null)
命令如果没有目录存在,则返回 0-print0
和 -0
的作用是让 xargs 命令处理目录名中的空格find -print0
和 xargs -0
也不是开箱即用的;但是当然,你可以通过 find -exec
避免它们,就像 Sylvain 的更新答案所演示的那样。 - tripleee我在目录树中有一些奇怪命名的文件,这让 awk
产生了困扰,就像 @AhmetAlpBalkan 的答案所述。因此,我采用了稍微不同的方法。
p=;
while read c;
do
l=${#c};
f=${p:0:$l};
if [ "$f" != "$c" ]; then
echo $c;
fi;
p=$c;
done < <(find . -type d | sort -r)
有一个名为Rawhide(RH)的替代工具,比find命令更易于使用。
对于除btrfs以外的文件系统:
rh 'd && nlink == 2'
btrfs:
rh 'd && "[ `rh -red %S | wc -l` = 0 ]".sh'
btrfs的更短/更快版本如下:
rh 'd && "[ -z \"`rh -red %S`\" ]".sh'
以上命令搜索目录,列出它们的子目录,并仅在没有匹配项时进行匹配(第一个通过计算输出行数,第二个通过检查每个目录是否有任何输出来实现)。
要在所有文件系统上以尽可能高效的方式工作的版本:
rh 'd && (nlink == 2 || nlink == 1 && "[ -z \"`rh -red %S`\" ]".sh)'
这个怎么样?它是便携式的,不依赖于棘手的链接计数。但请注意,重要的是将root/folder
放在末尾没有/。
find root/folder -type d | awk '{ if (length($0)<length(prev) || substr($0,1,length(prev))!=prev) print prev; prev=($0 "/") } END { print prev }'
关于这个问题,我的两点看法:
#!/bin/bash
(
while IFS= read -r -d $'\0' directory
do
files=$(ls -A "$directory" | wc -l)
if test $files -gt 0
then
echo "$directory"
fi
done < <(find . -type d -print0)
) | sort | uniq
find
命令中的-print0
选项是GNU扩展,不太可移植。在脚本中使用ls
命令始终是可疑的。 - tripleeedone
重定向到管道中就足够了。 - tripleee下面是一个适用于Linux和OS X的解决方案:
find . -type d -execdir bash -c '[ "$(find {} -mindepth 1 -type d)" ] || echo $PWD/{}' \;
或者:
find . -type d -execdir sh -c 'test -z "$(find "{}" -mindepth 1 -type d)" && echo $PWD/{}' \;
这个 awk
/sort
管道比最初提出的 在这个答案中 更好,但是它严重依赖于它 :) 它将更可靠地工作,无论路径是否包含正则表达式特殊字符:
find . -type d | sort -r | awk 'index(a,$0)!=1{a=$0;print}' | sort
请记住,awk
字符串是从1开始索引而不是从0开始索引的,如果您习惯于使用基于C的语言,则可能会感到奇怪。
如果当前行的索引在上一行中是1(即以它开头),那么我们跳过它,这就像匹配"^"$0
一样。
/a/a
和 /a/ab
,则不会报告 /a/a
。 - Ruudfind . -depth -type d | awk 'index(a,$0)!=1{a=$0;print}'
- Chubler_XL
find dir -type d \\( -not -exec ls -dA {} \; \\)
- Sylvain Defresne