Reputation: 846
I need to generate some images using ImageMagick. For this reason I prepare draw operation in variable before actually calling convert
, which looks like this
convert -size 160x160 xc:skyblue \
-fill 'rgb(200, 176, 104)' \
$draw_operations \
$0.png
$draw_operations contains lines, like these
-draw 'point 30,50' \
-draw 'point 31,50'
This call to convert
always results in
non-conforming drawing primitive definition `point` ...
unable to open image `'30,50'' ...
...
If I use $draw_operations with double quotes (which is required, if it contains multiple lines) the error is
unrecognized option `-draw 'point 30,50' '
Finally if I simply put -draw 'point 30,50'
as is, there is no error. So it's not related to ImageMagick, but rather to the way bash substitute variables.
Upvotes: 3
Views: 715
Reputation: 3380
Use eval
instead. That should interpret the spaces and quoting correctly:
#!/bin/bash
draw_operations="-draw 'point 30,50' \
-draw 'point 31,50'"
eval "convert -size 160x160 xc:skyblue \
-fill 'rgb(200, 176, 104)' \
"$draw_operations" \
"$0".png"
By the way, a useful debugging trick is to add set -x
at the beginning of your script. That will show you what commands are executed and how.
Note that, as @GordonDavisson points out in the comments, eval
is dangerous and will execute arbitrary code if, for example, your file name contains shell meta characters. I recommend you use his approach below which is both more elegant and safer.
Upvotes: 2
Reputation: 126098
See BashFAQ 50: I'm trying to put a command in a variable, but the complex cases always fail!. The problem is that the shell parses quotes and escapes before it expands variables, so putting quotes in a variable's value doesn't work -- by the time the quotes "are there", it's too late for them to do any good.
In this case, it looks to me like the best solution would be to store the arguments in an array, and then use "${array[@]}"
(including the double-quotes) to add them to the command. Something like this:
draw_operations=(-draw 'point 30,50' -draw 'point 31,50')
# Note that this creates an array with 4 elements, "-draw", "point 30,50", "-draw", and "point 31,50"
convert -size 160x160 xc:skyblue \
-fill 'rgb(200, 176, 104)' \
"${draw_operations[@]}" \
"$0.png"
You can also build the array incrementally, like this:
draw_operations=() # Start with an empty array
draw_operations+=(-draw 'point 30,50') # Add two elements
draw_operations+=(-draw 'point 31,50') # Add two more elements
...
Upvotes: 4