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

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


当前回答

到目前为止,没有一个回复正确地处理带有换行符的文件名(除了ChristopheD的,它是在我输入这篇文章时出现的)。下面不是一个shell一行程序,但是可以工作,并且相当快。

import os, sys

def names(roots):
    for root in roots:
        for a, b, basenames in os.walk(root):
            for basename in basenames:
                yield basename

sufs = set(os.path.splitext(x)[1] for x in names(sys.argv[1:]))
for suf in sufs:
    if suf:
        print suf

其他回答

不需要管道排序,awk可以做所有的事情:

find . -type f | awk -F. '!a[$NF]++{print $NF}'

我想这个还没有被提到:

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

另一种方法:

找到。-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是变量。

我发现它简单快捷……

   # find . -type f -exec basename {} \; | awk -F"." '{print $NF}' > /tmp/outfile.txt
   # cat /tmp/outfile.txt | sort | uniq -c| sort -n > tmp/outfile_sorted.txt

我的无awk、无sed、无perl、无python的posix兼容替代方案:

find . -type f | rev | cut -d. -f1 | rev  | tr '[:upper:]' '[:lower:]' | sort | uniq --count | sort -rn

诀窍在于它将行反转,并在开始处切断扩展。 它还将扩展名转换为小写。

示例输出:

   3689 jpg
   1036 png
    610 mp4
     90 webm
     90 mkv
     57 mov
     12 avi
     10 txt
      3 zip
      2 ogv
      1 xcf
      1 trashinfo
      1 sh
      1 m4v
      1 jpeg
      1 ini
      1 gqv
      1 gcs
      1 dv