Unix - 只列出包含子目录的目录

Unix - Only list directories which contain a subdirectory

如何在 Unix 中打印 shell 树中包含其他目录的目录数?

我还没有找到像 findls 这样的命令的解决方案。

您可以使用find命令:find . -type d -not -empty

这将打印每个不为空的子目录。您可以使用 -maxdepth.

控制搜索的深度

要打印号码,您可以使用wc -l

find . -type d -not -empty | wc -l

如果您生成一个特定目录下所有目录的列表,然后从名称中删除最后一个部分,您将得到一个包含子目录的目录列表,但该列表中可能有重复项。因此,您需要 post-process 列表,产生(作为第一个近似值):

find ${base:-.} -type d |
sed 's%/[^/]*$%%' |
sort -u

查找变量$base中列出的目录下的所有目录,默认为当前目录,并打印它们的名称。该代码假定您没有名称中带有换行符的目录。如果这样做,可以进行修复,但最好的修复方法是重命名目录。 sed 命令删除最后一个斜杠及其后的所有内容。排序消除了重复条目。剩下的是包含子目录的目录列表。

嗯,或多或少。有一种退化的情况需要考虑:列表中的顶级目录将被列出,无论它们是否有子目录。解决这个问题有点困难。在删除尾随 material 之前,您需要删除与指定给 find 的目录完全匹配的任何输出行。所以,你需要这样的东西:

{
printf '\#^%s$#d\n' ${base:-.}
echo 's%/[^/]*$%%'
} > sed.script
find ${base:-.} -type d |
sed -f sed.script |
sort -u
rm -f sed.script

\#^%s$#d 假定您不在目录名称中使用 #。如果确实要使用它,则需要找到一个不在名称中使用的字符(可能是 Control-A)并用它代替 #。如果您绝对可以面对任何字符,那么您将需要做更多的工作来转义一些晦涩的字符,例如 Control-A,当它出现在目录名称中时。

还有一个问题:使用像 sed.script 这样的固定名称作为临时文件名是不好的(出于多种原因——例如两个人试图同时 运行 脚本相同的目录,尽管它也可能存在安全风险),因此使用 mktemp 创建一个临时文件名:

tmp=$(mktemp ${TMPDIR:-/tmp}/dircnt.XXXXXX)
trap "rm -f $tmp; exit 1" 0 1 2 3 13 15
{
printf '\#^%s$#d\n' ${base:-.}
echo 's%/[^/]*$%%'
} > $tmp
find ${base:-.} -type d |
sed -f $tmp |
sort -u
rm -f $tmp
trap 0

这处理最常见的信号(HUP、INT、QUIT、PIPE、TERM)并删除临时文件,即使其中之一到达也是如此。

显然,如果您只想计算目录的数量,可以通过 wc -l 将上述命令的输出通过管道传输来获取计数。

ls -1d */*/. | cut -d / -f1 | uniq