如何计算具有特定扩展名的文件及其所在目录?

赞娜

我想知道.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。

muru

我没有使用符号链接检查输出,但是:

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
  • 然后我将其与awk进行汇总,以获取文件总数以及包含这些文件的目录数。请注意,d此处与基本上相同NR我本可以省略1sed命令中的插入,而只是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] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

计算具有特定扩展名的特定目录中的文件总数

如何将所有具有特定扩展名的文件移动到特定目录?

从多个目录复制具有特定扩展名的文件

如何在python目录中计算具有两种扩展名的文件?

如何从tar文件的根目录中提取具有特定扩展名的文件?

如何忽略一个目录及其子目录中的特定扩展名的所有文件?

如何使用Python递归复制目录中具有特定扩展名的所有文件?

如何获取目录中具有特定扩展名的所有文件?

(Python) - 如何计算具有特定扩展名或名称的文件中的文件数

如何将具有特定扩展名的文件从子目录移动到另一个目录,包括使用 CMD 创建文件所在的子目录?

如何在目录中递归添加具有特定扩展名的文件

如何查找具有特定扩展名的文件,而仅排除当前目录中的某些名称?

如何从目录中仅读取具有特定扩展名的文件

如何计算Android上具有特定扩展名的文件数?

如何从特定给定的目录和所有子目录中搜索具有特定扩展名的文件

R:计算不同子目录/文件夹中具有特定扩展名的文件数

如何仅在具有Powershell的txt文件的目录中列出具有特定扩展名的文件?

如何获取目录树中具有特定文件扩展名的每个文件的目录名称?

如何附加到具有特定扩展名的文件

如何使用Shell脚本从特定目录创建指向具有特定扩展名的所有文件的符号链接?

如果使用python在该目录中找到具有特定扩展名的文件,如何移动整个目录?

将具有特定扩展名的文件从目录移动到 PHP 中的子目录

从所有子目录复制具有特定扩展名的所有文件

列出具有特定扩展名的目录和文件数量,构建特定菜单

在特定目录及其子目录中,找到所有以 .tmp 扩展名结尾的文件夹

提取具有特定文件扩展名的文件并保持目录结构?

Bash:如何对具有特定扩展名的文件使用“查找”,但它还会给出其先前的目录

列出 Scala 目录下具有特定扩展名的所有文件

列出具有特定扩展名的目录中的所有文件