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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2962723/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-17 22:09:17  来源:igfitidea点击:

resizing images with imagemagick via shell script

bashimagemagick

提问by jml

I don't really know that much about bash scripts OR imagemagick, but I am attempting to create a script in which you can give some sort of regexp matching pattern for a list of images and then process those into new files that have a given filename prefix.

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

for example given the following dir listing:

例如给出以下目录列表:

allfiles01.jpg allfiles02.jpg allfiles03.jpg

allfiles01.jpg allfiles02.jpg allfiles03.jpg

i would like to call the script like so:

我想像这样调用脚本:

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

the end result of this would be that you get a bunch of new files with newnames, the numbers match up,

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

so far what i have is:

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

IMAGELIST=
RESIEZFACTOR=
NUMIMGS=length($IMAGELIST)

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

Thanks for any help... The parts that I obviously need help with are 1. how to give a bash script matching criteria that it understands 2. how to use the $2 without having it match the 2nd item in the image list 3. how to get the length of the image list 4. how to create a proper for loop in such a case 5. how to do proper text replacement for a shell command whereby you are appending items as i allude to.

感谢您的帮助...我显然需要帮助的部分是 1. 如何提供一个匹配它理解的标准的 bash 脚本 2. 如何使用 $2 而不让它与图像列表中的第二项匹配 3. 如何获取图像列表的长度 4. 如何在这种情况下创建适当的 for 循环 5. 如何对 shell 命令进行适当的文本替换,您将在其中添加我提到的项目。

jml

jml

回答by David Z

Probably the way a standard program would work would be to take an "in" filename pattern and an "out" filename pattern and perform the operation on each file in the current directory that matches the "in" pattern, substituting appropriate parts into the "out" pattern. This is pretty easy if you have a hard-coded pattern, when you can write one-off commands like

标准程序的工作方式可能是采用“输入”文件名模式和“输出”文件名模式,并对当前目录中与“输入”模式匹配的每个文件执行操作,将适当的部分替换到“出”模式。如果你有一个硬编码的模式,这很容易,当你可以编写一次性命令时

for infile in *.jpg; do convert $infile -filter bessel -resize 30% ${infile//allfiles/newnames}; done

In order to make a script that will do this with any pattern, though, you need something more complicated because your filename transformation might be something more complicated than just replacing one part with another. Unfortunately Bash doesn't really give you a way to identify what part of the filename matched a specific part of the pattern, so you'd have to use a more capable regular expression engine, like sedfor example:

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

#!/bin/bash

inpattern=
factor=
outpattern=
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

That could be invoked as

这可以被称为

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

(note the single quotes!) and it would resize allfiles1.jpgto newnames1.jpg, etc. But then you'd wind up basically having to learn sed's regular expression syntax to specify your in and out patterns. (It's not that bad, really)

(注意单引号!)它会调整allfiles1.jpgnewnames1.jpg,等等。但是你最终基本上必须学习sed的正则表达式语法来指定你的输入和输出模式。(没那么糟,真的)

回答by gldunne

You could eliminate the regex problem if you make a folder of all the files to be processed, and then run something like:

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

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

Then, if you need to rename them all later, you could do something like:

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

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

Also, If you are doing a batch process of the same operation, you might see if using mogrify might help (imagemagik's method for converting multiple files). Like the above example, it's always good to make a copy of the folder, and then run any processing so you don't destroy your original files.

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

回答by Paused until further notice.

Your script should be called using a syntax such as:

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

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

and use getoptsto process the options. What you may not be aware of is that the shell expands the file glob before the script gets it so the way you had your arguments your script would never be able to distinguish the filenames from the other parameters.

并用于getopts处理选项。您可能不知道的是,shell 在脚本获取文件之前扩展了文件 glob,因此您使用参数的方式将永远无法将文件名与其他参数区分开来。

Output files will be named using the renamescript often found on systems with Perl installed. A file named "allfiles03.jpg" will be output as "newname03.jpg".

输出文件将使用rename安装了 Perl 的系统上常见的脚本命名。名为“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

This is untested (obviously since most of the arguments to convertare missing).

这是未经测试的(显然是因为convert缺少大部分参数)。

Parameter validation such as range checks, missing required options and others are left as exercises for further development. Also absent are checks for successful completion of one step before continuing to the next one. Also issues such as locations of files and name collisions and others are not addressed.

参数验证(例如范围检查、缺少所需选项等)留作进一步开发的练习。在继续下一个步骤之前,也没有检查是否成功完成了一个步骤。还没有解决诸如文件位置和名称冲突等问题。