在bash中匹配* .jpg而不是* .foo.jpg

时间:2015-08-31 23:31:57

标签: bash glob

这一定很简单,但我无法弄清楚。

for filename in *[^\.foo].jpg
do
echo $filename
done

echo代替匹配的文件名,显示模式:

+ echo '*[^.foo].jpg'
*[^.foo].jpg

意图是查找所有以.jpg结尾但不以.foo.jpg结尾的文件。

编辑:按照(被误解的)建议尝试:

for filename in *[!".foo"].jpg

还没有!

2 个答案:

答案 0 :(得分:6)

你实际上可以用extglob这样做。要演示,复制并粘贴以下代码:

shopt -s extglob
cd "$(mktemp -d "${TMPDIR:-/tmp}/test.XXXXXX")" || exit
touch hello.txt hello.foo hello.foo.jpg hello.jpg
printf '%q\n' !(*.foo).jpg

输出应为:

hello.jpg

答案 1 :(得分:2)

在bash中,如果glob模式没有匹配,bash将返回模式本身。您可以使用nullglob shell选项更改此行为,该选项可以像这样打开:

shopt -s nullglob

bash手册页中标题为Filename Expansion的部分对此进行了描述。

至于为什么它不匹配,只是你没有任何匹配的文件。这可能是由于您使用的^通常不是有效的glob元字符。就glob而言,^只是匹配文字^。此外,[...]可能不会做你认为它做的事情。

有关有效的glob元字符的说明,请参阅bash手册页的Pattern Matching部分。

你不能写一个glob模式,它返回“所有以.jpg结尾但不以.foo.jpg结尾的文件”。最简单的方法是对所有jpg文件(*.jpg)进行全局处理,然后过滤出代码块内foo.jpg结尾的文件。

for filename in *.jpg
do
    [[ $filename = *.foo.jpg ]] && continue
    echo $filename
done