我正在用音频文件做一些事情,其中大部分但不是全部是 mp3 文件。现在我只想对非 mp3 文件或没有扩展名的文件运行一些命令.mp3
。
我认为自己非常擅长正则表达式,但不太擅长文件通配,这在意想不到的方面有微妙的不同。
我环顾四周,从其他 SO & SE 答案中了解到,Bash 具有“扩展的通配符”,允许我这样做:
file ../foo/bar/*.!(mp3)
但我的一些文件名除了形成文件扩展名的点之外还包含点:
../foo/bar/Naked_Scientists_Show_19.10.15.mp3
../foo/bar/YWCS_ep504-111519-pt1_5ej4_41cc9320.mp3_42827d48daefaa81ec09202e67fa8461_24419113.mp3
../foo/bar/eLife_Podcast_19.09.26.mp3
../foo/bar/gdn.sci.080428.bg.science_weekly.mp3
看起来全局从第一个点开始匹配,而不是从最后一个点开始匹配。我查看了文档,但似乎它们远不如正则表达式强大。但我并没有真正理解所有内容,因为我没有花太多时间在 *nix shell 上。
我是否错过了一些仍然可以通过 Bash 通配符来做到这一点的方法?如果没有,使用 find 或其他工具实现相同目的的方法仍然值得了解。
答案1
*.!(mp3)
匹配 onfoo.bar.mp3
因为 thatfoo.
后面跟着bar.mp3
is不是mp3
。
您想要!(*.mp3)
这里,它匹配任何不以 结尾的内容.mp3
。
如果您想匹配名称中至少包含一个.
(除了会使它们成为隐藏文件的前导文件)但不以 结尾的文件.mp3
,您可以这样做!(*.mp3|!(*.*))
。
无论如何,请注意,除非您bash
是使用 构建的--enable-extended-glob-default
,否则您需要shopt -s extglob
使 ksh glob 运算符可用。
答案2
shell
GLOBIGNORE
变量可用于限制与模式匹配的文件名集。如果GLOBIGNORE
设置,GLOBIGNORE
则将从匹配列表中删除也与其中模式之一匹配的每个匹配文件名。如果nocaseglob
设置了该选项,则执行与 中的模式的匹配GLOBIGNORE
,而不考虑大小写。当设置且不为空时,文件名.
和..
始终被忽略 。GLOBIGNORE
但是,设置GLOBIGNORE
为非空值具有启用dotglob
shell 选项的效果,因此以 ' ' 开头的所有其他文件名.
都将匹配。要获得忽略以 ' ' 开头的文件名的旧行为.
,请将 '.*
' 设为GLOBIGNORE
.未设置时该dotglob
选项将被禁用。GLOBIGNORE
$ touch a.b.mp3 .c.mp3 foo.tgz .bar
$ echo *
a.b.mp3 foo.tgz
$ shopt -s extglob; echo *.!(mp3)
a.b.mp3 foo.tgz
$ GLOBIGNORE='*.mp3'; echo *
.bar foo.tgz
答案3
我能想到的最简单的方法:
find ${path-to-folder} -type f | grep -vE ".*\.mp3$"
您可以找到文件夹中的所有文件并将其通过管道传输到反向扩展 grep:
查找某个位置的所有文件
find ${path-to-folder} -type f
反向 grep 并使用正则表达式按扩展名进行过滤
grep -vE ".*\.mp3$"
Grep 标志:
-v
反向grep-E
扩展 grep(使用正则表达式)
正则表达式解释:
.*
表示从 0 到任何字符数,任何可能的字符\.
寻找实际的点mp3
对于形成扩展名的字符串$
代表停产
答案4
可能不适合你的情况,但我想知道如何用纯函数创建一个函数Bash
,然后将扩展名作为参数传递,如果你想将它添加到你的bashrc
并且你想在将来做同样的事情,这会很方便,像下面这样
所以,基本上我们正在做的是正则表达式检查您想要的扩展。
for file in *; do
if [[ $file =~ \.mp3$ ]]; then
echo $file
fi
done
在函数中实现它:这将输出当前目录中具有特定扩展名的所有文件。
getFileByExt(){
local extension="$1"
if (( $# == 1 )); then
for file in *; do
if [[ $file =~ \.$extension$ ]]; then
echo $file
fi
done
else
echo "Usage: ${FUNCNAME[0]} <extension>"
## If run from bashrc, return the name of function
fi
}
现在,例如要获取所有具有扩展名的文件mp3
,只需执行以下操作即可简单:
getFileByExt mp3
并获取没有特定扩展名的文件:这将输出当前目录中没有特定扩展名的所有文件。
getFileWithoutExt(){
local extension="$1"
if (( $# == 1 )); then
for file in *; do
if [[ ! $file =~ \.$extension$ ]]; then
echo $file
fi
done
else
echo "Usage: ${FUNCNAME[0]} <extension>"
fi
}
类似地,要获取没有mp3
扩展名的文件,只需执行以下操作:
getFileWithoutExt mp3
欲了解更多信息:
https://stackoverflow.com/questions/407184/how-to-check-the-extension-of-a-filename-in-a-bash-script