我正在使用ImageMagick bash工具,该工具使用以下形式的命令:
<command> <input filename> <stuff> <output filename>
我正在尝试执行以下命令:
<command> x.png <stuff> x.png
但是对于目录中的每个文件。我试过了:
<command> *.png <stuff> *.png
但那没用。在目录中的每个文件上执行此类命令的正确方法是什么?
答案 0 :(得分:4)
许多Unix命令行工具(例如awk
,sed
,grep
都是基于流的或面向行的,这意味着它们一次处理一行文件。使用这些时,必须将输出写入中间文件,然后将其重命名(使用mv
)回原始输入文件。原因是你可能在读完所有内容之前在输入文件上写字,所以你会破坏你的输入。在这种情况下,@ sjsam的答案是绝对正确的 - 特别是因为他小心翼翼地使用中间的&&
,以便在命令不成功时不执行mv
。
然而,在ImageMagick及其convert
,compare
,compose
命令的特定情况下,这是 NOT 的情况。这些程序是面向文件的,而不是面向行的,因此在写入任何输出之前,它们会将整个输入文件读入内存。原因是他们经常需要知道图像中是否有任何透明像素才能开始处理,或者图像中有多少种颜色,他们在读取整个文件之前就无法知道。因此,它是完全安全的,事实上惯用使用相同的输入文件名作为输出文件名,如下所示:
convert image.jpg ... -crop 100x100 -colors 16 ... image.jpg
在回答您的问题时,当您要处理多个文件时,首选方法是使用专门用于处理多个文件的mogrify
工具(也是ImageMagick套件的一部分)。所以,你会这样做:
mogrify -crop 100x100 -colors 16 *.jpg
会用结果覆盖你的输入文件 - 这就是你要求的。如果您不希望它覆盖您的输入文件,您可以添加-path
告诉ImageMagick输出目录的路径,如下所示:
mogrify -path /path/to/thumbnails -thumbnail -colors 16 *.jpg
如果你有太多的文件让Windows COMMAND.EXE / CMD.EXE扩展并传递给mogrify
,你可以让ImageMagick像这样在内部展开glob(星号)并且能够处理无限数量的文件:
mogrify -crop 100x100 '*.jpg'
重点是,mogrify
语法不仅简洁,而且可以跨Windows / OSX / Linux移植,这也意味着您只需要创建单个进程来完成所有工作图像,而不是必须编写FOR
循环,并为每个潜在的数千个文件创建并执行convert
进程和mv
进程 - 因此效率更高并且不易出错。
答案 1 :(得分:1)
对于单个文件,请执行以下操作:
<command> x.png <stuff> temp.png && mv temp.png x.png
对于一组文件,请执行以下操作:
#!/bin/bash
find `pwd` -name \*.png | while read line
do
<command> "$line" <stuff> temp.png && mv temp.png "$line"
done
将脚本保存在包含png文件的文件夹中processpng
。使它成为可执行文件并运行它。
./processpng
上面脚本的一般版本,它将包含上述文件的文件夹的路径作为参数,如下所示:
#!/bin/bash
find $1 -name \*.png | while read line
do
<command> "$line" <stuff> temp.png && mv temp.png "$line"
done
将脚本保存为processpng
计算机中的任何位置。使其成为可执行文件并运行它:
./processpng /path/to/your/png/folder
修改强>
结合@ anishsane的解决方案,实现同样的紧凑方式 结果将是
#!/bin/bash
find $1 -name \*.png -exec bash -c "<command> {} <stuff> temp.png && mv temp.png {}"
在find .... -exec
:
{}
表示(包含)查找表达式中的结果。注意 空的花括号{}对shell没有特殊意义所以我们可以 离开而不逃避{}
注意:强调我的。
参考:此AskUbuntu Question。