匹配 *.jpg 但不匹配 bash 中的 *.foo.jpg

Matching *.jpg but not *.foo.jpg in bash

这一定很简单,但我想不通。

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

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

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

目的是查找所有以 .jpg 结尾但不以 .foo.jpg.

结尾的文件

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

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

还没有!

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

shopt -s nullglob

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

至于为什么不匹配,很简单,就是你没有匹配的文件。这可能是由于您使用的 ^ 通常不是有效的 glob 元字符。就 glob 而言,^ 只是匹配文字 ^。此外,[...] 可能也不会按照您的想法去做。

有关有效 glob meta-characters 的解释,请参阅 bash 手册页的 Pattern Matching 部分。

您不能编写 returns "all files ending in .jpg but not .foo.jpg." 的 glob 模式。最简单的做法是遍历所有 jpg 文件 (*.jpg),然后在代码块中过滤掉以 foo.jpg 结尾的文件。

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

您实际上可以使用 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