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

3

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

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

3个回答

2

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

这将打印出每个非空的子目录。您可以使用-maxdepth控制搜索的深度。

要打印数字,您可以使用wc -l

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

1
-empty 命令是否符合要求?它在目录中查找文件;即使目录中不包含子目录,但包含文件的目录也不为空。 - Jonathan Leffler
1
@JonathanLeffler 很好的观点,根据man页面,它也适用于目录,并且使用“-type d”可以指定只查看目录。 - Paulo Bu
谢谢!现在我想计算这些子目录中有多少个也包含目录。这是我目前的代码:'find -mindepth 2 -maxdepth 2'但是有时候一个子目录包含多个目录,所以它会被列出多次。我只想检查它是否有一个或多个,然后“添加”到我的列表中,而不是每次找到一个目录就添加一次。 - Stein

0
如果您生成一个特定目录下所有目录的列表,然后从名称中删除最后一个组件,您将得到包含子目录的目录列表,但该列表中可能会有重复项。因此,您需要对列表进行后处理,以产生(作为第一近似):
find ${base:-.} -type d |
sed 's%/[^/]*$%%' |
sort -u

查找变量$base中列出的目录下的所有目录,默认为当前目录,并打印它们的名称。代码假定您没有目录名称中包含换行符。如果有,请修复,但最好的解决方法是重命名该目录。sed命令从路径中移除最后一个斜杠和其后面的所有内容。排序功能可消除重复条目。剩下的是包含子目录的目录列表。

嗯,或多或少。还有一种特殊情况需要考虑:不管是否有子目录,列表中的顶级目录都将被列出。修复这个问题比较困难。您需要在删除尾部内容之前消除任何与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来获取计数。


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

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