在Linux机器上,我希望遍历一个文件夹层次结构,并获得其中所有不同文件扩展名的列表。

从外壳中实现这一点的最佳方法是什么?


当前回答

因为已经有了另一个使用Perl的解决方案:

如果你安装了Python,你还可以这样做(从shell):

python -c "import os;e=set();[[e.add(os.path.splitext(f)[-1]) for f in fn]for _,_,fn in os.walk('/home')];print '\n'.join(e)"

其他回答

我认为最简单直接的方法是

for f in *.*; do echo "${f##*.}"; done | sort -u

它是根据克里斯托夫的第三种方法改进的。

我想这个还没有被提到:

find . -type f -exec sh -c 'echo "${0##*.}"' {} \; | sort | uniq -c

递归版本:

find . -type f | sed -e 's/.*\.//' | sed -e 's/.*\///' | sort -u

如果你想要总数(有多少次扩展被看到):

find . -type f | sed -e 's/.*\.//' | sed -e 's/.*\///' | sort | uniq -c | sort -rn

非递归(单个文件夹):

for f in *.*; do printf "%s\n" "${f##*.}"; done | sort -u

我是根据这个论坛帖子写的,功劳应该在那里。

在Python中,为非常大的目录使用生成器,包括空白扩展名,并获取每个扩展名出现的次数:

import json
import collections
import itertools
import os

root = '/home/andres'
files = itertools.chain.from_iterable((
    files for _,_,files in os.walk(root)
    ))
counter = collections.Counter(
    (os.path.splitext(file_)[1] for file_ in files)
)
print json.dumps(counter, indent=2)

另一种方法:

找到。-type f -name "*。*" -printf "%f\n" | while if = read -r;执行“${REPLY##*.}”;完成|排序-u

您可以删除名称“*”。*”,但这确保我们只处理具有某种扩展名的文件。

printf是find的print,不是bash的。-printf "%f\n"只打印文件名,剥离路径(并添加换行符)。

然后使用字符串替换,使用${REPLY##*.}删除到最后一个点。

注意$REPLY只是read的内置变量。我们可以用我们自己的形式:while IFS= read -r file,这里$file是变量。