如何在文件夹层次结构中找到所有不同的文件扩展名?
- 2024-10-31 08:38:00
- admin 原创
- 44
问题描述:
在 Linux 机器上,我想要遍历文件夹层次结构并获取其中所有不同文件扩展名的列表。
从 shell 中实现这一目标的最佳方法是什么?
解决方案 1:
试试这个(不确定这是否是最好的方法,但它有效):
find . -type f | perl -ne 'print $1 if m/.([^./]+)$/' | sort -u
其工作原理如下:
查找当前文件夹中的所有文件
打印文件扩展名(如果有)
制作一个独特的排序列表
解决方案 2:
不需要管道sort
,awk 可以完成所有工作:
find . -type f | awk -F. '!a[$NF]++{print $NF}'
解决方案 3:
我的无 awk、无 sed、无 Perl、无 Python 的 POSIX 兼容替代方案:
find . -name '*.?*' -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
解决方案 4:
递归版本:
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
" "${f##*.}"; done | sort -u
我根据这个论坛帖子得出了这个结论,功劳应该归于此。
解决方案 5:
Powershell:
dir -recurse | select-object extension -unique
感谢http://kevin-berridge.blogspot.com/2007/11/windows-powershell.html
解决方案 6:
添加了我自己的变体。我认为这是所有变体中最简单的一种,当效率不是主要考虑因素时很有用。
find . -type f | grep -oE '.(w+)$' | sort -u
解决方案 7:
查找所有以点开头的字符并仅显示后缀。
find . -type f -name "*.*" | awk -F. '{print $NF}' | sort -u
如果你知道所有后缀都有 3 个字符,那么
find . -type f -name "*.???" | awk -F. '{print $NF}' | sort -u
或者使用 sed 显示所有包含一到四个字符的后缀。将 {1,4} 更改为后缀中预期的字符范围。
find . -type f | sed -n 's/.*.(.{1,4})$//p'| sort -u
解决方案 8:
我尝试了这里的很多答案,甚至是“最佳”答案。它们都没有达到我所追求的具体目标。所以,除了过去 12 个小时坐在多个程序的正则表达式代码中阅读和测试这些答案之外,这就是我想出的完全符合我要求的答案。
find . -type f -name "*.*" | grep -o -E ".[^.]+$" | grep -o -E "[[:alpha:]]{2,16}" | awk '{print tolower($0)}' | sort -u
查找所有可能有扩展名的文件。
仅 Greps 扩展
查找 2 到 16 个字符之间的文件扩展名(如果不符合您的需要,只需调整数字)。这有助于避免缓存文件和系统文件(系统文件位用于搜索 jail)。
Awk 以小写形式打印扩展名。
排序并仅引入唯一值。最初我曾尝试使用 awk 答案,但它会重复打印大小写敏感度不同的项目。
如果您需要计算文件扩展名的数量,请使用以下代码
find . -type f -name "*.*" | grep -o -E ".[^.]+$" | grep -o -E "[[:alpha:]]{2,16}" | awk '{print tolower($0)}' | sort | uniq -c | sort -rn
尽管这些方法需要一些时间才能完成,并且可能不是解决问题的最佳方法,但它们确实有效。
更新:根据@alpha_989,长文件扩展名会导致问题。这是由于原始正则表达式“[[:alpha:]]{3,6}”造成的。我已更新答案以包含正则表达式“[[:alpha:]]{2,16}”。但是,使用此代码的任何人都应该知道,这些数字是最终输出允许的扩展长度的最小值和最大值。超出该范围的任何内容都将在输出中分成多行。
注意:原始帖子确实写道“- 查找 3 到 6 个字符之间的文件扩展名(如果不符合您的需要,只需调整数字)。这有助于避免缓存文件和系统文件(系统文件位用于搜索 jail)。”
想法:可以通过以下方式查找超过特定长度的文件扩展名:
find . -type f -name "*.*" | grep -o -E ".[^.]+$" | grep -o -E "[[:alpha:]]{4,}" | awk '{print tolower($0)}' | sort -u
其中 4 是需要包含的文件扩展名的长度,然后还查找超出该长度的任何扩展名。
解决方案 9:
在 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)
解决方案 10:
由于已经有另一个使用 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 '
'.join(e)"
解决方案 11:
另一种方法:
`find . -type f -name "." -printf "%f
" | while IFS= read -r; do echo "${REPLY##*.}"; done | sort -u`
您可以删除-name "*.*"
,但这可确保我们只处理具有某种扩展名的文件。
-printf
isfind
的打印,而不是 bash。仅`-printf "%f
"`打印文件名,剥离路径(并添加换行符)。
然后我们使用字符串替换来删除最后一个点${REPLY##*.}
。
请注意,这$REPLY
只是read
的内置变量。我们也可以按照以下形式使用自己的变量:while IFS= read -r file
,这里 $file 就是变量。
解决方案 12:
到目前为止,没有一个回复能够正确处理带换行符的文件名(除了 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
解决方案 13:
我认为最简单直接的方法是
for f in *.*; do echo "${f##*.}"; done | sort -u
它是根据 ChristopheD 的第 3 种方式修改的。
解决方案 14:
我认为还没有提到这一点:
find . -type f -exec sh -c 'echo "${0##*.}"' {} ; | sort | uniq -c
解决方案 15:
接受的答案使用 REGEX,并且您无法使用 REGEX 创建别名命令,您必须将其放入 shell 脚本中,我正在使用 Amazon Linux 2 并执行以下操作:
我将接受的答案代码放入文件中,使用方法如下:
sudo vim 查找命令
添加此代码:
find ./ -type f | perl -ne 'print $1 if m/.([^./]+)$/' | sort -u
输入以下命令保存文件: :wq!
sudo vim ~/.bash_profile
alias getext=". /path/to/your/find.sh"
:wq!
. ~/.bash_profile
解决方案 16:
你也可以这样做
find . -type f -name "*.php" -exec PATHTOAPP {} +
解决方案 17:
我发现它简单又快捷......
# 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
解决方案 18:
如果您正在寻找这方面的答案.gitignore
,请查看以下答案。
git ls-tree -r HEAD --name-only | perl -ne 'print $1 if m/.([^./]+)$/' | sort -u
解决方案 19:
Ondra Žižka 的另一个版本:
find . -name '*.?*' -type f | rev | cut -d. -f1 | rev | sort | uniq
在区分大小写的文件系统中,我认为不同的大小写不应被视为相同的扩展名。此外,我认为没有必要通过计算文件数量来回答 OP 的问题。
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理必备:盘点2024年13款好用的项目管理软件