我想创建一个 bash 函数,它的行为就像wc -l
对多个文件的行为一样,用于计算一组目录中文件数量的行数。wc -l
工作原理如下:
wc -l test.zip tt.zip zzz.zip | sort
17 tt.zip
2015 test.zip
6567 zzz.zip
8599 total
我希望我的函数如何处理文件:
count dir1 dir2 dir3 | sort:
1 dir1
144 dir2
1000 dir3
1145 total
其中 dir{1..3} 是 3 个目录,显示的文件数包括隐藏文件。
我已经做了什么:
#/bin/bash
count() {
if [ "`file -b $1`" == 'directory' ] ; then
echo `la "$1" | wc -l`
else
wc -l "$@" | sort
fi
}
我可以用 for 循环来实现它$@
,但我更愿意找到一个更简单的解决方案。如果你还能帮我包含每个目录的大小。你会让我非常高兴!
答案1
尝试:
find dir1 dir2 dir3 -maxdepth 1 -type f -printf '%h\n' | awk '{c[$0]++} END{for (dir in c) printf "%6i %s\n",c[dir],dir}' | sort -n
如果在中指定了目录$@
,则使用:
find "$@" -maxdepth 1 -type f -printf '%h\n' | awk '{c[$0]++} END{for (dir in c) printf "%6i %s\n",c[dir],dir}' | sort -n
怎么运行的
find dir1 dir2 dir3 -maxdepth 1 -type f -printf '%h\n'
这将查找目录 dir1、dir2 和 dir3 中的所有常规文件。对于找到的每个文件,都会打印其目录。
-maxdepth 1
(可选)告诉 find 不要深入子目录。-type f
告诉 find 仅报告常规文件。对于找到的每个文件,-printf '%h\n'
告诉 find 打印文件所在的目录。awk '{c[$0]++} END{for (dir in c) printf "%6i %s\n",c[dir],dir}'
这将计算每个目录在输入中出现的次数。读取完所有输入后,它将打印总数。
我们使用关联数组
c
来计算每个目录被看到的次数。在 awk 中,$0
是当前正在读取的行的内容。c[$0]
是迄今为止该行被看到的次数。c[$0]++
将该计数加一。sort -n
这将按文件数量的升序对输出进行排序。(
-n
告诉 sort 按数字顺序排序而不是按字母顺序排序。)
例子
假设我们有包含以下文件的目录:
$ ls dir{1..3}/*
dir1/a.txt dir1/c.txt dir1/e.txt dir1/f.txt dir2/b.txt dir2/d.txt dir2/f.txt dir3/b.txt
dir1/b.txt dir1/d.txt dir1/file3.txt dir2/a.txt dir2/c.txt dir2/e.txt dir3/a.txt
我们的命令产生输出:
$ find dir1 dir2 dir3 -maxdepth 1 -type f -printf '%h\n' | awk '{c[$0]++} END{for (dir in c) printf "%6i %s\n",c[dir],dir}' | sort -n
2 dir3
6 dir2
7 dir1
改进:添加总行
$ find dir1 dir2 dir3 -maxdepth 1 -type f -printf '%h\n' | awk '{c[$0]++} END{for (dir in c) {printf "%6i %s\n",c[dir],dir;tot+=c[dir]}; printf "%6i TOTAL",tot }' | sort -n
2 dir3
6 dir2
7 dir1
15 TOTAL
如果输出中只有一个目录,则禁止打印 TOTAL:
find "$@" -maxdepth 1 -type f -printf '%h\n' | awk '{c[$0]++} END{for (dir in c) {printf "%6i %s\n",c[dir],dir;tot+=c[dir]}; if (length(c)>1)printf "%6i TOTAL",tot }' | sort -n
在输出中包含空目录
还包括空目录:
find "$@" -maxdepth 1 -type f -printf '%h\n' | awk 'FNR==NR{c[$0]=0; next} {c[$0]++} END{for (dir in c) {printf "%6i %s\n",c[dir],dir;tot+=c[dir]}; if (length(c)>1)printf "%6i TOTAL",tot }' <(printf "%s\n" "$@") <(cat) | sort -n
作为示例,我们考虑一个空目录:
$ ls dir4
让我们设置$@
:
$ set -- dir4
现在,让我们运行代码:
$ find "$@" -maxdepth 1 -type f -printf '%h\n' | awk 'FNR==NR{c[$0]=0; next} {c[$0]++} END{for (dir in c) {printf "%6i %s\n",c[dir],dir;tot+=c[dir]}; if (length(c)>1)printf "%6i TOTAL",tot }' <(printf "%s\n" "$@") <(cat) | sort -n
0 dir4
让我们用两个目录再试一次:
$ set -- dir1 dir4
$ find "$@" -maxdepth 1 -type f -printf '%h\n' | awk 'FNR==NR{c[$0]=0; next} {c[$0]++} END{for (dir in c) {printf "%6i %s\n",c[dir],dir;tot+=c[dir]}; if (length(c)>1)printf "%6i TOTAL",tot }' <(printf "%s\n" "$@") <(cat) | sort -n
0 dir4
7 dir1
7 TOTAL