我想知道.c
在一个复杂的大型目录结构中有多少个常规文件具有扩展名,以及这些文件分布在多少个目录中。我想要的输出就是那两个数字。
我已经看到了有关如何获取文件数量的问题,但是我也需要知道文件所在目录的数量。
.
或开头,-
并带有空格或换行符。.c
符号链接,以及指向目录的符号链接。我不希望遵循或计数符号链接,或者我至少想知道是否以及何时对其进行计数。.c
文件。我匆匆在(Bash)shell中写了一些命令来自己计算,但我认为结果不正确...
shopt -s dotglob
shopt -s globstar
mkdir out
for d in **/; do
find "$d" -maxdepth 1 -type f -name "*.c" >> out/$(basename "$d")
done
ls -1Aq out | wc -l
cat out/* | wc -l
这会输出有关重定向不明确的投诉,丢失当前目录中的文件,并使用特殊字符触发(例如,重定向的find
输出会在文件名中显示换行符)并写入一大堆空文件(哎呀)。
如何可靠地枚举我的.c
文件及其包含的目录?
如果有帮助,可以使用以下命令创建带有错误名称和符号链接的测试结构:
mkdir -p cfiles/{1..3}/{a..b} && cd cfiles
mkdir space\ d
touch -- i.c -.c bad\ .c 'terrible
.c' not-c .hidden.c
for d in space\ d 1 2 2/{a..b} 3/b; do cp -t "$d" -- *.c; done
ln -s 2 dirlink
ln -s 3/b/i.c filelink.c
在结果结构中,有7个目录包含.c
文件,而29个常规文件以.c
(在dotglob
运行命令时关闭)结尾(如果我记错了,请告诉我)。这些是我想要的号码。
请随时不要使用此特定测试。
注意:任何外壳或其他语言的答案都将由我测试和赞赏。如果我必须安装新软件包,则没问题。如果您知道GUI解决方案,我建议您分享(但是我可能不会安装整个DE来测试它):)我使用Ubuntu MATE 17.10。
我没有使用符号链接检查输出,但是:
find . -type f -iname '*.c' -printf '%h\0' |
sort -z |
uniq -zc |
sed -zr 's/([0-9]) .*/\1 1/' |
tr '\0' '\n' |
awk '{f += $1; d += $2} END {print f, d}'
find
命令将打印.c
找到的每个文件的目录名称。sort | uniq -c
将为我们提供每个目录中有多少个文件(sort
此处可能是不必要的,不确定)sed
,我将目录名称替换为1
,从而消除了所有可能的怪异字符,只剩下了count和1
剩余的字符tr
d
此处与基本上相同NR
。我本可以省略1
在sed
命令中的插入,而只是NR
在此处打印出来,但是我认为这会更清晰一些。直到为止tr
,数据都是NUL分隔的,对于所有有效的文件名而言都是安全的。
使用zsh和bash,您可以printf %q
用来获取带引号的字符串,该字符串中没有换行符。因此,您可能可以执行以下操作:
shopt -s globstar dotglob nocaseglob
printf "%q\n" **/*.c | awk -F/ '{NF--; f++} !c[$0]++{d++} END {print f, d}'
但是,即使**
不应该扩展到目录的符号链接,我也无法在bash 4.4.18(1)(Ubuntu 16.04)上获得所需的输出。
$ shopt -s globstar dotglob nocaseglob
$ printf "%q\n" ./**/*.c | awk -F/ '{NF--; f++} !c[$0]++{d++} END {print f, d}'
34 15
$ echo $BASH_VERSION
4.4.18(1)-release
但是zsh可以正常工作,并且可以简化命令:
$ printf "%q\n" ./**/*.c(D.:h) | awk '!c[$0]++ {d++} END {print NR, d}'
29 7
D
使该glob可以选择点文件,.
选择常规文件(因此不选择符号链接),并且:h
仅打印目录路径,而不打印文件名(如find
的%h
)(请参阅“文件名生成和修饰符”部分)。因此,使用awk命令,我们只需要计算出现的唯一目录数,而行数就是文件数。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句