如何在Unix Shell中打印包含其他目录的树中目录的数量?
我还没有找到像find
或ls
这样的命令的解决方案。
如果生成特定目录下所有目录的列表,然后从名称中删除最后一个组件,则将获得包含子目录的目录列表,但是该列表中可能会重复。因此,您需要对列表进行后处理,产生(作为第一近似值):
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
用管道传输上述命令的输出以获取计数。
您可以使用find
命令:find . -type d -not -empty
ls -1d */*/. | cut -d / -f1 | uniq