使用ls和grep列出具有某些扩展名的文件


152

我只想从当前目录中获取文件,仅输出.mp4 .mp3 .exe文件即可。所以我想我可以这样做:

ls | grep \.mp4$ | grep \.mp3$ | grep \.exe$

但是不会,因为第一个grep仅输出mp4,因此不会使用其他2个grep。

有任何想法吗?PS,在慢豹上运行此脚本。


1
这确实是错误的方法-代替使用grep,先使用shopt -s nullglob,然后再参考*.exe *.mp3 *.mp4。见mywiki.wooledge.org/ParsingLs
Charles Duffy

1
我不知道“慢豹”是否是错字...
Wowfunhappy

1
@Wowfunhappy哈哈哈,绝对是错字,我记得当时以为雪豹很快。
造币厂

Answers:


335

为什么不:

ls *.{mp3,exe,mp4}

我不确定我从哪里学到的-但是我一直在使用它。


1
这不适用于我,因为我使用的扩展名是用于目录的,因此ls列出了目录的内容。
理查德·文布尔

1
@RichardVenable添加-d开关以防止递归目录。
2013年

11
我喜欢这种解决方案,但是如果您缺少任何一种文件类型,它似乎都会失败。例如,您拥有mp3,但没有.exe(Mac OSX,zsh)
JHo 2013年

2
我将stderr重定向到/ dev / null以避免ls: *.exe: No such file or directory例如:ls *.{zip,tar.gz,tar} 2>/dev/null
Isaac

1
当我直接在shell中运行ls foo *。{tar.gz,zip}时,它可以工作,但是当将其放在shell脚本中时,latest ==(ls -I'.done'-tr $ {pkgprefix}。{tar。 gz,zip} |尾部-1)我收到一条错误消息:ls:无法访问'bamtools *。{tar.gz,zip}':没有这样的文件或目录,任何更聪明的人都可以完善答案。
Kemin Zhou,

41

使用正则表达式find

find . -iregex '.*\.\(mp3\|mp4\|exe\)' -printf '%f\n'

如果您要传递文件名:

find . -iregex '.*\.\(mp3\|mp4\|exe\)' -printf '%f\0' | xargs -0 dosomething

这样可以保护包含空格或换行符的文件名。

find当使用-E(增强)选项时,OS X 仅支持交替。

find -E . -regex '.*\.(mp3|mp4|exe)'

2
在Mac OS X上:find . -iregex '.*\(mp3\|mp4\|exe\)'
andilabs

3
安迪,在Mac OS上对我不起作用。但这确实是:find -E。-regex'。*(mp3 | mp4 | exe)'
Joseph Johnson

此解决方案将加载以下文件:mysupermp3.jpg考虑$在正则表达式的末尾和\\.扩展名之前添加
Panthro,2017年

1
@Panthro:其实不会。查找似乎使用隐式锚。点是个好主意(只需要一个反斜杠)。
暂停,直到另行通知。

38

egrep -扩展grep-在这里有帮助

ls | egrep '\.mp4$|\.mp3$|\.exe$'

应该做的工作。


而已!谢谢刚刚意识到我应该使它不区分大小写,所以我在使用:ls | egrep -i'\ .mp4 $ | \ .mp3 $ | \ .exe $如果其他人在这一天需要帮助。我总是对我的回答感到惊讶。
造币厂的

我看不到这将如何工作。没有任何选项的ls会在列中产生输出。锚定到行尾将无法正确匹配。
camh

4
@camh:ls到终端(或带有-C选件)会产生多列输出。ls到管道(或-1)的管道具有单列输出。(将输出ls与进行比较ls | cat)。
暴徒

末尾有一个撇号。除此之外,它似乎还可以工作。
比约恩

12

最简单的方法是只使用ls

ls *.mp4 *.mp3 *.exe

2
谢谢,但是我已经尝试过了,并且我不喜欢没有文件时出现的错误。您可以通过以下方法解决此问题:ls * .mp4 * .mp3 * .exe 2> / dev / null现在只想到了这一点:P
Mint

1
我很惊讶ls没有某种沉默的选择。
MitMaro

2
在bash中,您可以执行“ set -o nullglob”,而不会得到错误。
camh

2
我的错误-应该是“ shopt -s nullglob”,而不是set -o命令
camh,2009年

1
或只使用“ echo”:echo * .mp4 * .mp3 * .exe
Adrian Pronk

9

以防万一:为什么不使用find

find -iname '*.mp3' -o -iname '*.exe' -o -iname '*.mp4'

我发现这可以代替- find . -name '*.mkv' -o -name '*.flv'(根据需要添加-o子句)。我需要使用.来指示目录和标记,-name而不是-iname-我在macOS 10.13上。
克里斯,

6

无需grep。Shell通配符可以解决问题。

ls *.mp4 *.mp3 *.exe

如果您已经跑步

shopt -s nullglob

那么不匹配的glob将被完全删除,并且不会留在命令行中未展开。

如果要使用不区分大小写的通配符(因此* .mp3将匹配foo.MP3):

shopt -s nocaseglob

与我对《好时光部落》的评价相同。
薄荷

1
我正在尝试将此-R选项与列出子目录中匹配文件的选项一起使用,但是该选项似乎没有任何效果,并且我仍然只获得当前目录的结果。
克里斯,

3

如果您仍在寻找替代解决方案:

ls | grep -i -e '\\.tcl$' -e '\\.exe$' -e '\\.mp4$'

如果需要,可以随时添加更多-e标志。


3

对于OSX用户

如果使用ls *.{mp3,exe,mp4},如果其中一个扩展名没有结果,它将引发错误

使用ls *.(mp3|exe|mp4)会返回与这些扩展名匹配的所有文件,即使其中一个扩展名具有0结果


5
使用您的示例出现语法错误???'bash:意外令牌附近的语法错误'('
nagordon

2
我想你的意思是ls *.@(mp3|exe|mp4)。您需要shopt -s extglob为此工作。顺便说一句,ls也没用,你可以做printf '%s\n' *.@(mp3|exe|mp4)
gniourf_gniourf

1
我在macOS 10.13上收到语法意外的令牌消息
克里斯,克里斯,

1
ls | grep "\.mp4$
\.mp3$
\.exe$"

谢谢,但是用完几行有点不方便。
薄荷

+ mdfind产生了有史以来最好/最快的搜索! mdfind -name querystring | grep "\.h$" 查找文件标题中带有quesrystring的所有标题。pronto。
亚历克斯·格雷


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.