我编写了一个脚本来转换文件夹中的图像。该脚本使用 for 循环:
我=“1” 对于 *.jpg 中的文件;执行 输出文件=$(echo "图像"$(echo $i)) 转换“$file”-调整大小 50x50 $outputFile i=$[i+1] 完毕
我想要做的是允许脚本在多种文件类型扩展上运行。现在我尝试这样做:
对于 *.jpg *.JPG *.jpeg 中的文件;执行 .... 完毕
我遇到的问题是,如果您所在的文件夹中全是 *.JPG 而没有 *.jpg,即使没有图像,脚本仍会触发 i+1,因为它无论如何都会运行 for 循环,如果找不到任何 *.jpg,它就会转到 *.JPG。
我如何才能定位多个文件扩展名,而无需它按类型自行运行?例如,它们的语法是否类似于:
对于 [*.jpg | *.JPG] 中的文件;执行 ...
?
这样,我的输出文件夹将始终包含带有如下标签的图像:
image1.jpg
image2.jpg
image3.jpg
等等。
而不是因为没有 *.jpg 可以先运行而导致文件夹缺少 image1.jpg。
答案1
解决方案
使用 nullglob。将以下行放在循环之前for
:
shopt -s nullglob
nullglob
意味着如果没有这样的文件,则从列表中删除 glob。观察没有 nullglob 的情况:
$ echo *.jpg *.JPG *.jpeg
test.jpg *.JPG *.jpeg
现在,使用 nullglob:
$ shopt -s nullglob
$ echo *.jpg *.JPG *.jpeg
test.jpg
修改后的脚本
完整的脚本可能是:
i=1
shopt -s nullglob
for file in *.jpg *.JPG *.jpeg; do
convert "$file" -resize 50x50 "image$i.jpg"
i=$((i+1))
done
三点说明:
在 的定义中
outputFile
,所有这些echo
陈述都是不必要的。按照惯例,我在输出文件名中添加了扩展名
.jpg
。如果您确实不想要该扩展名,只需将其删除即可。我
$[...]
用更标准的形式替换:$((...))
。
答案2
由于您想寻找多个清楚的(不区分大小写)扩展, John1024 的回答包含
shopt -s nullglob
非常好用。如果你只是在寻找
*.jpg
、*.JPG
和其他六种大小写字母的组合,最简单的方法就是for file in *.[Jj][Pp][Gg]
查找名称为
- (某事),然后
.
(句号),然后是J
或j
,然后P
或p
,然后G
或者g
换句话说,
- (某事),然后
.
(句号),然后是- “jpg”,以大写和小写字母的组合形式呈现
解决你的问题的方法之一是
shopt -s nullglob for file in *.[Jj][Pp][Gg] *.[Jj][Pp][Ee][Gg] do …
这个
[…]
技巧很有用,但还有更好的方法。如果我告诉你有一个名为的 shell 选项nocaseglob
,你能猜出它的作用吗?shopt -s nullglob nocaseglob for file in *.jpg *.jpeg do …
所以现在
*.jpg
意味着- (某事),然后
.
(句号),然后是- “jpg”,以大写和小写字母的组合形式呈现
因此上述命令将匹配
*.jpg
、*.JPG
、*.Jpg
、*.jpeg
、*.jPeG
等。另一种方法是使用
extglob
shell 选项来启用扩展模式匹配运算符。你仍然需要nullglob
和nocaseglob
。扩展模式匹配运算符都看起来像(一些特殊字符) ( 模式列表 )
为了清晰起见,添加了空格,并且
pattern-list
是以下列表pattern
s 用|
字符分隔。对你的目的来说最有趣的是@(模式列表)
这意味着匹配列出的模式之一。所以现在脚本变成了
shopt -s nullglob nocaseglob extglob for file in *.@(jpg|jpeg) do …
这看起来可能要多输入一些代码,但随着扩展数量的增加,权衡也会发生变化。考虑一下,
for file in *.@(jpg|jpeg|jfif|exif|tif|tiff|gif|bmp|png|svg)
比
for file in *.jpg *.jpeg *.jfif *.exif *.tif *.tiff *.gif *.bmp *.png *.svg
你从哪里学会的
$(echo …)
?当然,肯定有用,甚至有时有用,但你用得太多了。说$(some_command(s) …)
$(echo …)
outputFile="image$i"
你甚至可能不需要引号(在赋值语句中)。
好的,你可以原谅仅此一次,因为您知道 的值
outputFile
是良性的,因为您将其设置为非空白、非特殊字符的常量字符串(image
)加上一个变量,您将该变量设置为非空白、非特殊字符的常量字符串(1
),并且只对其进行了简单的算术运算。但是,作为一般规则,您应该总是引用所有对 shell 变量的引用,除非你有很好的理由不这样做,并且你确定你知道自己在做什么。所以你的convert
命令,理想情况下应该是convert "$file" -resize 50x50 "$outputFile"
(带有引号
$outputFile
)。
答案3
您可能想要替换此部分:
for file in *.jpg; do
这样:
for file in $(ls *.jpg *.JPG); do