关于linux:如何在文件夹层次结构中找到所有不同的文件扩展名?

How can I find all of the distinct file extensions in a folder hierarchy?

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

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


试试这个(不确定这是不是最好的方法,但它是有效的):

1
find . -type f | perl -ne 'print $1 if m/\.([^.\/]+)$/' | sort -u

其工作原理如下:

  • 查找当前文件夹中的所有文件
  • 打印文件扩展名(如果有)
  • 创建唯一的排序列表


不需要管到sort,awk可以做到这一切:

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


递归版本:

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

如果需要总计(查看扩展的5月份次数):

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

非递归(单个文件夹):

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

我是根据这个论坛帖子写的,信用卡应该放在那里。


Powershell:

1
dir -recurse | select-object extension -unique

感谢http://kevin-berridge.blogspot.com/2007/11/windows-powershell.html


找到所有带点的东西,只显示后缀。

1
find . -type f -name"*.*" | awk -F. '{print $NF}' | sort -u

如果你知道所有后缀都有3个字符,那么

1
find . -type f -name"*.???" | awk -F. '{print $NF}' | sort -u

或者使用sed显示所有后缀,其中包含一到四个字符。将1,4更改为后缀中需要的字符范围。

1
find . -type f | sed -n 's/.*\.\(.\{1,4\}\)$/\1/p'| sort -u


加入我自己的变种。我认为这是最简单的一批,当效率不是一个大问题时,它是有用的。

1
find . -type f | grep -o -E '\.[^\.]+$' | sort -u


我在这里试了很多答案,甚至是最好的答案。他们都没有达到我所追求的目标。所以除了在过去的12个小时里坐在多个程序的regex代码中,阅读和测试这些答案之外,这就是我想到的,我想要的工作方式。

1
 find . -type f -name"*.*" | grep -o -E"\.[^\.]+$" | grep -o -E"[[:alpha:]]{2,16}" | awk '{print tolower($0)}' | sort -u
  • 查找可能具有扩展名的所有文件。
  • 只增加扩展名
  • greps用于2到16个字符之间的文件扩展名(如果不适合您的需要,只需调整数字)。这有助于避免缓存文件和系统文件(系统文件位用于搜索监狱)。
  • 以小写形式打印扩展名。
  • 排序并只引入唯一的值。最初,我曾试图尝试awk答案,但它将双重打印的项目,在案件敏感性不同。

如果需要文件扩展名的计数,请使用以下代码

1
find . -type f -name"*.*" | grep -o -E"\.[^\.]+$" | grep -o -E"[[:alpha:]]{2,16}" | awk '{print tolower($0)}' | sort | uniq -c | sort -rn

虽然这些方法需要一段时间才能完成,而且可能不是解决问题的最佳方法,但它们是有效的。

更新:每@alpha_长文件扩展名都会导致问题。这是由于原始的regex"[:alpha:]3,6"。我已经更新了答案,包括regex"[:alpha:]2,16"。但是,使用此代码的任何人都应该知道,这些数字是最终输出允许扩展的最小值和最大值。超出该范围的任何内容都将在输出中拆分为多行。

注意:原来的帖子读到了"-greps文件扩展名在3到6个字符之间(只是调整数字,如果他们不适合你的需要)。这有助于避免缓存文件和系统文件(系统文件位用于搜索监狱)。"

想法:可以通过以下方式查找特定长度的文件扩展名:

1
 find . -type f -name"*.*" | grep -o -E"\.[^\.]+$" | grep -o -E"[[:alpha:]]{4,}" | awk '{print tolower($0)}' | sort -u

其中4是要包含的文件扩展名长度,然后查找超出该长度的任何扩展名。


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

1
2
3
4
5
6
7
8
9
10
11
12
13
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)

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

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

诀窍是,它将线反转,并在开始处切断延长线。它还将扩展名转换为小写。

实例输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
   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


我认为这件事还没有提到:

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


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

如果安装了python,也可以(从shell)执行以下操作:

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


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

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

它是在克里斯托夫的第三条道路上修改的。


到目前为止,所有的回复都没有正确地处理换行的文件名(除了Christophed的,这是我刚输入的)。下面的不是壳牌一号衬里,而是工作的,而且速度相当快。

1
2
3
4
5
6
7
8
9
10
11
12
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

你也可以这样做

1
find . -type f -name"*.php" -exec PATHTOAPP {} +