如何在Unix shell中打印树中包含其他目录的目录数?
我还没有找到像find
或ls
这样的命令的解决方案。
你可以使用find
命令:find . -type d -not -empty
这将打印出每个非空的子目录。您可以使用-maxdepth
控制搜索的深度。
要打印数字,您可以使用wc -l
。
find . -type d -not -empty | wc -l
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
来获取计数。
ls -1d */*/. | cut -d / -f1 | uniq
-empty
命令是否符合要求?它在目录中查找文件;即使目录中不包含子目录,但包含文件的目录也不为空。 - Jonathan Leffler