使用imagemagick通过shell脚本调整图像大小

时间:2010-06-03 01:04:33

标签: bash imagemagick

我真的不太了解bash脚本或imagemagick,但我正在尝试创建一个脚本,您可以在其中为图像列表提供某种正则表达式匹配模式,然后将这些模式处理为具有的新文件给定的文件名前缀。

例如给出以下目录列表:

  

allfiles01.jpg allfiles02.jpg   allfiles03.jpg

我想像这样调用脚本:

./resisemany.sh allfiles*.jpg 30 newnames*.jpg

这样做的最终结果是你会得到一堆带有新名字的新文件,数字匹配,

到目前为止,我所拥有的是:

IMAGELIST=$1
RESIEZFACTOR=$2
NUMIMGS=length($IMAGELIST)

for(i=0; i<NUMIMGS; i++)
  convert $IMAGELIST[i] -filter bessel -resize . RESIZEFACTOR . % myfile.JPG

感谢您的帮助...... 我显然需要帮助的部分是 1.如何给bash脚本匹配它理解的标准 2.如何使用$ 2而不匹配图像列表中的第二项 3.如何获取图像列表的长度 4.在这种情况下如何创建适当的for循环 5.如何为shell命令进行正确的文本替换,以便按照我的要求附加项目。

JML

3 个答案:

答案 0 :(得分:6)

标准程序的工作方式可能是采用“in”文件名模式和“out”文件名模式,并对当前目录中与“in”模式匹配的每个文件执行操作,替换相应的部分进入“外出”模式。如果你有一个硬编码模式,当你可以编写像

这样的一次性命令时,这很容易
for infile in *.jpg; do convert $infile -filter bessel -resize 30% ${infile//allfiles/newnames}; done

为了制作一个可以用任何模式执行此操作的脚本,您需要更复杂的东西,因为您的文件名转换可能比仅用一个部分替换另一个部分更复杂。不幸的是,Bash并没有真正为您提供一种方法来确定文件名的哪个部分与模式的特定部分匹配,因此您必须使用功能更强大的正则表达式引擎,例如sed

#!/bin/bash

inpattern=$1
factor=$2
outpattern=$3
for infile in *; do
    outfile=$(echo $infile | sed -n "s/$inpattern/$outpattern/p")
    test -z $outfile && continue
    convert $infile -filter bessel -resize $factor% $outfile
done

可以作为

调用
./resizemany.sh 'allfiles\(.*\).jpg' 30 'newnames\1.jpg'

(请注意单引号!)并将allfiles1.jpg调整为newnames1.jpg等等。但是,您最终必须学习sed的正则表达式语法指定您的进出模式。 (这不是那么糟糕,真的)

答案 1 :(得分:5)

如果你创建了一个要处理的所有文件的文件夹,然后运行如下命令,你可以消除正则表达式问题:

for img in `ls *.jpg`
do
  convert $img -filter bessel -resize 30% processed-$img
done

然后,如果您以后需要重命名它们,您可以执行以下操作:

ls | nl -nrz -w2 | while read a b;  do mv "$b" newfilename.$a.jpg; done;

此外,如果您正在执行相同操作的批处理,您可能会看到使用mogrify是否有帮助(imagemagik的转换多个文件的方法)。与上面的示例一样,制作文件夹的副本,然后运行任何处理以便不破坏原始文件总是好的。

答案 2 :(得分:1)

应使用以下语法调用您的脚本:

./resizemany.sh -r 30 -n newnames -o allfiles allfiles*.jpg

并使用getopts处理选项。你可能没有意识到的是shell在脚本获取之前扩展了文件glob,所以你的参数的方式你的脚本永远无法区分文件名和其他参数。

输出文件将使用安装了Perl的系统上常见的rename脚本命名。名为“allfiles03.jpg”的文件将输出为“newname03.jpg”。

#!/bin/bash

options=":r:n:o:"
while getopts $options option
do
    case $option in
        n)
            newnamepattern=$OPTARG
            ;;
        o)
            oldnamepattern=$OPTARG
            ;;
        r)
            resizefacor=$OPTARG
            ;;

        \?)
            echo "Invalid option"
            exit 1
    esac
done
# a check to see if any options are missing should be performed (not implemented)
shift $((OPTIND - 1))
# now all that's left will be treated as filenames
for file
do
    convert (input options) "$file" -resize $resizefactor (output options) "${file}.out" 
    rename "s/$old/$new/;s/\.out$//" "${file}.out"
done

这是未经测试的(显然因为convert的大多数参数都缺失了。)

参数验证(例如范围检查,缺少必需选项等)留作进一步开发的练习。同样缺席是在继续下一步之前成功完成一步的检查。此外,诸如文件位置和名称冲突等问题也未得到解决。