我想删除分辨率小于 228x228 的多张图片。为此,我编写了以下 shell 脚本:
#!/bin/bash
for i in $( ls ); do
if [$(identify -format "%w" $i) < 228] && [$(identify -format "%h" $i) < 228];
then
rm $i
fi
done
由于某些原因,我在运行它时得到了这个输出:
./del.sh: line 4: [640: command not found
./del.sh: line 4: [550: command not found
./del.sh: line 4: [315: command not found
...
你能告诉我这个脚本有什么问题以及如何修复它吗?
谢谢。
编辑:即使在括号后添加了空格,我仍然会收到错误。这是由于使用了<
而不是 造成的-lt
,并且已修复。现在没有错误了。
答案1
这里有一些问题:首先,测试中的表达式[…]
周围需要空格(陷阱#10),其次,该比较<
不适用于[…]
测试(陷阱#7)。您需要-lt
(少于)或改用[[…]]
,这是一个巴什主义。另外,for
循环应该被替换(陷阱#1)。
所以:
for i in ./*; do
if [ -e "$i" ]; then
if [ $(identify -format "%w" "$i") -lt 228 ] && [ $(identify -format "%h" "$i") -lt 228 ];
then
rm -- "$i"
fi
fi
done
您可能还希望避免调用identify
两次来获取两个维度(陷阱 #58),而是只调用一次并让它打印一个字符串,以便在 shell 语法中用作变量赋值。
如果我们写
identify -format "width=%w height=%h" "$i"
它会打印出类似这样的内容width=50 heigth=250
。当我们eval
评估该字符串时,我们只需一次调用即可设置两个变量,条件可以写成:
eval "$(identify -format "width=%w height=%h" "$i")"
if [ $width -lt 228 ] && [ $height -lt 228 ];
then
rm -- "$i"
fi
也可以看看:常见的 bash 陷阱。
答案2
我不会使用循环,而是使用find
with-exec
和-delete
:
find . -maxdepth 1 -type f \
-exec sh -c '
[ $(identify -format "%w" "$1") -lt 228 ] &&
[ $(identify -format "%h" "$1") -lt 228 ]' _ {} \; \
-delete -print
这还将打印被删除的文件,-print
如果您不想要,可以将其删除。
答案3
目的并非回答,而是为了提供一个有用的提示,对我编写 bash 脚本有很大帮助。
有一个名为 shell 脚本 linter 的工具shellcheck
,可以捕获 bash 脚本中的一些常见错误,还可以避免一些陷阱。它可以像 ubuntu 中的任何软件包一样安装 ->https://launchpad.net/ubuntu/+source/shellcheckuniverse
目前处于稳定状态。
这是脚本的输出
shellcheck del.sh
In del.sh line 4:
if [$(identify -format "%w" $i) < 228] && [$(identify -format "%h" $i) < 228];
^-- SC1009: The mentioned parser error was in this if expression.
^-- SC1073: Couldn't parse this test expression.
^-- SC1035: You need a space after the [ and before the ].
^-- SC1020: You need a space before the ].
^-- SC1072: Missing space before ]. Fix any mentioned problems and try again.
如果您修复并再次应用,您将获得已在接受的答案中提到的一些其他建议和修复。