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

334

在 Linux 機器上,我想遍歷一個文件夾層次結構並獲取其中所有不同的文件擴展名列表。

從 shell 中實現這個任務的最佳方法是什麼?

18个回答

4

另一种方法:

find . -type f -name "*.*" -printf "%f\n" | while IFS= read -r; do echo "${REPLY##*.}"; done | sort -u

你可以省略 -name "*.*",但这样做确保我们仅处理具有某些扩展名的文件。

-printffind 的打印功能,而不是 bash。 -printf "%f\n" 仅打印文件名,并去除路径(并添加换行符)。

然后,我们使用字符串替换来删除最后一个点及其之前的所有内容,使用 ${REPLY##*.}

请注意,$REPLY 只是 read 内置变量的简写。我们也可以使用类似 while IFS= read -r file 的形式来定义自己的变量,这里 $file 就是变量。


2
接受的答案使用了正则表达式,你不能使用正则表达式创建别名命令,你必须把它放到一个shell脚本中。我正在使用Amazon Linux 2,并执行以下操作:
1. 使用sudo vim find.sh将接受的答案代码放入文件中。
在文件中添加以下代码:
find ./ -type f | perl -ne 'print $1 if m/\.([^.\/]+)$/' | sort -u

通过输入以下命令来保存文件::wq!

  1. sudo vim ~/.bash_profile

  2. alias getext=". /path/to/your/find.sh"

  3. :wq!

  4. . ~/.bash_profile


2
我认为还没有人提到这个问题:

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

这可能会非常缓慢,因为每个文件都需要生成一个新进程。 - Ondra Žižka

2

到目前为止,除了ChristopheD的回答(在我打字时刚好出现),其他回答都没有正确处理带有换行符的文件名。以下虽然不是一行命令,但可以正常工作且速度较快。

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

2
我认为最简单和直接的方法是:
for f in *.*; do echo "${f##*.}"; done | sort -u

这是基于ChristopheD的第三种方式进行了修改。


0

你也可以这样做

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

0
如果你正在寻找关于 .gitignore 的答案,请查看下面的回答。
git ls-tree -r HEAD --name-only | perl -ne 'print $1 if m/\.([^.\/]+)$/' | sort -u 

0

我发现它简单快捷...

   # 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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接