Answers:
您可以使用find
和uniq
,例如:
$ find . -type f | sed 's/.*\.//' | sort | uniq -c
16 avi
29 jpg
136 mp3
3 mp4
命令说明
find
递归打印所有文件名sed
从每个文件名删除前缀,直到文件扩展名uniq
假设输入已排序
-c
进行计数(如直方图)。*.php?blah=blah&foo=bar
带有各种参数,因此将它们全部视为唯一文件。我如何修改它以寻找*.php*
?
sed 's/^.*\(\.[a-zA-Z0-9][a-zA-Z0-9][a-zA-Z0-9]\).*$/\1/'
find -name '.*' -prune -o -type f -print
评估如下:如果目录条目匹配,.*
则对其进行修剪,否则,如果它是文件,则进行打印。由于.*
还匹配.
,即CWD,因此将删除所有内容,即find甚至都不会下降到第一个目录中。也许是2岁的find
行为有所不同-或那只是我的疏忽。无论如何,find -name '.*' -not -name . -prune -o -type f -print
解决此问题。
这种单线似乎是一个相当健壮的方法:
find . -type f -printf '%f\n' | sed -r -n 's/.+(\..*)$/\1/p' | sort | uniq -c
该find . -type f -printf '%f\n'
打印树中的每个常规文件的基本名称,没有目录。消除不必担心可能有目录.
的在他们在您的sed
正则表达式。
在sed -r -n 's/.+(\..*)$/\1/p'
只有它的扩展取代了传入文件名。例如,.somefile.ext
变为.ext
。注意.+
正则表达式中的首字母;这将导致任何匹配在扩展名之前至少需要一个字符.
。这样可以防止像这样的文件名.gitignore
被当作完全没有名称,并且扩展名“ .gitignore”可能就是您想要的。如果没有,请更换.+
了.*
。
该行的其余部分来自已接受的答案。
编辑:如果您想要帕累托图格式的排序良好的直方图,只需sort
在末尾添加另一个即可:
find . -type f -printf '%f\n' | sed -r -n 's/.+(\..*)$/\1/p' | sort | uniq -c | sort -bn
来自构建的Linux源代码树的样本输出:
1 .1992-1997
1 .1994-2004
1 .1995-2002
1 .1996-2002
1 .ac
1 .act2000
1 .AddingFirmware
1 .AdvancedTopics
[...]
1445 .S
2826 .o
2919 .cmd
3531 .txt
19290 .h
23480 .c
我已经将bash脚本放到~/bin
名为exhist
以下内容的文件夹中:
#!/bin/bash
for d in */ ; do
echo $d
find $d -type f | sed -r 's/.*\/([^\/]+)/\1/' | sed 's/^[^\.]*$//' | sed -r 's/.*(\.[^\.]+)$/\1/' | sort | uniq -c | sort -nr
# files only | keep filename only | no ext -> '' ext | keep part after . (i.e. ext) | count | sort by count desc
done
无论我在哪个目录中,我都只需键入“ exh”,使用制表符自动完成该操作,然后会看到类似以下内容的内容:
$ exhist
src/
7 .java
1 .txt
target/
42 .html
10 .class
4 .jar
3 .lst
2
1 .xml
1 .txt
1 .properties
1 .js
1 .css
PS在问号后修剪部分应该很容易与另一个sed命令一起执行(可能在最后一个命令之后执行)(我没有尝试过): sed 's/\?.*//'