【问题标题】:How to find all file extensions recursively from a directory?如何从目录中递归查找所有文件扩展名?
【发布时间】:2011-06-27 06:21:27
【问题描述】:

我可以使用什么命令或命令集合来返回目录(包括子目录)中的所有文件扩展名?

目前,我正在使用 lsgrep 的不同组合,但找不到任何可扩展的解决方案。

【问题讨论】:

    标签: bash terminal grep


    【解决方案1】:

    这个怎么样:

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

    【讨论】:

    • 查找[此目录](文件)(匹配任何带有扩展名的名称)|使用 sed 替换句号之前的任何内容 |使用唯一标志排序
    • 但这不会进入子目录。
    • @BhaskarChakradhar 是的。是什么让你认为它没有?
    • 谢谢,这个很有用,我在 chromium 源代码目录中使用这个,得到了数千个文件扩展名,其中许多实际上是没有文件扩展名的文件,有没有忽略所有文件没有文件扩展名?
    【解决方案2】:

    列出所有扩展及其当前和所有子目录的计数

    ls -1R | sed 's/[^\.]*//' | sed 's/.*\.//' | sort | uniq -c
    

    【讨论】:

      【解决方案3】:
      find . -type f | sed 's|.*\.||' | sort -u
      

      也适用于 mac。

      【讨论】:

      • 此解决方案不能确保列出的所有文件具有 扩展名,因此没有它们的文件不会被 sed 修复,而是被视为 扩展名。
      【解决方案4】:

      如果您使用的是 Bash 4+

      shopt -s globstar
      for file in **/*.*
      do
        echo "${file##*.}
      done
      

      Ruby(1.9+)

      ruby -e 'Dir["**/*.*"].each{|x|puts x.split(".")[-1]}' | sort -u
      

      【讨论】:

      • 对于我使用MSYS2,模式"${file##*.}" 只会打印带有两个点的扩展名的最后部分(例如,当扩展名是.tar.gz 时,它只会打印.gz)。模式"${file#*.} 打印扩展的每个部分。
      【解决方案5】:

      另一个使用 find 的解决方案(甚至应该正确地对嵌入换行符的文件扩展名进行排序):

      # [^.]: exclude dotfiles
      find . -type f -name "[^.]*.*" -exec bash -c '
        printf "%s\000" "${@##*.}"
      ' argv0 '{}' + |
      sort -uz | 
      tr '\0' '\n'
      

      【讨论】:

        【解决方案6】:

        另外一个:

        find * | awk -F . {'print $2'} | sort -u
        

        【讨论】:

        • echo 'gniourf.tar.gz' | awk -F . {'print $2'} 给出tarecho 'one.two.three.pdf' | awk -F . {'print $2'} 给出two。你确定你的方法是好的吗?
        • 我认为上面的解决方案是一个简单的解决方案,这里我再放一个 find 。 -type f -name "." | awk -F。 '!a[$NF]++{print $NF}' 。我不认为使用简单的命令就无法获取每种类型的文件。正如你之前所说,解析每一行都会出现一些问题,所以在这种情况下,我确信最好在 python、perl 或类似的脚本中使用一些脚本,这样你就不会遇到这个问题。无论如何,我提出了一个简单的解决方案,如果您现在可以使用 grep 过滤文件的扩展名 | grep 'txt\|png\|pdf'。谢谢
        【解决方案7】:
        ls -1 | sed 's/.*\.//' | sort -u
        

        更新: 你是对的,马修。根据您的评论,以下是更新版本:

        ls -R1 | egrep -C 0 "[^\.]+\.[^\./:]+$" | sed 's/.*\.//' | sort -u

        【讨论】:

        • 这有两个问题。首先,它仅适用于平面目录,但缺​​少子目录。其次,它在输出中包含所有没有扩展名的文件。
        • Don't parse the output of ls,尤其是当它没用的时候。
        • 如果您有时间先安装它,您真的应该使用 ripgrep 而不是 egrep:github.com/BurntSushi/ripgrep,更新后的命令将是:ls -R1 | rg -C 0 "[^\.]+\.[^\./:]+$" | sed 's/.*\.//' | sort -u 对于大型文件夹,我得到至少 10 倍的改进。跨度>
        【解决方案8】:

        当我在谷歌搜索一个好的答案时,我很快就尝试了这个。我比 Bash 更倾向于正则表达式,但这也适用于子目录。我也不认为包含没有扩展名的文件:

        ls -R | egrep '(\.\w+)$' -o | sort | uniq -c | sort -r

        【讨论】:

        【解决方案9】:

        另一个,与其他类似,但只使用两个程序(find 和 awk)

        find ./ -type f -name "*\.*" -printf "%f\n" | awk -F . '!seen[$NF]++ {print $NF}'

        -type f 将其限制为仅文件,而不是目录

        -name "*\.*" 确保文件名中包含.

        -printf "%f\n" 只打印文件名,而不是文件名的路径。

        -F . 让 awk 使用句点作为字段分隔符。

        $NF 是最后一个字段,以句点分隔。

        !seen[$NF]++ 在第一次遇到扩展时评估为真,每次遇到扩展时评估为假。

        print $NF 打印扩展名。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-08-21
          • 1970-01-01
          • 2012-11-06
          • 2010-12-14
          • 1970-01-01
          • 2020-03-25
          相关资源
          最近更新 更多