Bash: a space in the value of the variable, which is subsequently used as a parameter

When writing a bash script to help create a polaroid sketch using the Imagick convert command. I ran into a problem. Although I manage to get around this (actually, since convert is flexible enough), I still want to know how to solve this problem without such a workaround.

Basically, a bash script will get a header value that may contain a space. I want to use this header as a convert parameter. If the title is empty (''), I will not use the '-caption' parameter for the convert command. Like this:

 CAPTION="Is this Cute?" # The actual value will be tacked from the parameter of this bash. IN_FILE="resources/puppy.png" OUTFILE="resources/puppy_polaroid.png" # If CAPTION is not empty, reformat CAPTION if [ "$CAPTION" != "" ]; then CAPTION="-caption \"$CAPTION\""; fi # otherwise, do not use '-caption' add all COMMAND="convert $CAPTION \"$IN_FILE\" \"$OUTFILE\"" echo "Command: $COMMAND" #This echo a value command `$COMMAND` 

The echo repeats the value command, which can be copied, inserted into the terminal, and started. BUT bash does not start. How can i do this?

NOTE. In the case of convert , -caption "" do the job. I know this and am currently using it as a job.

Thanks in advance for your help.

EDIT: From the answer, here is the code that works for me now.

 ... # Get CAPTION and GRAVITY from parameters if [ "$CAPTION" != "" ]; then ARGS_CAPTION=(-caption "$CAPTION"); fi if [ "$GRAVITY" != "" ]; then ARGS_GRAVITY=(-gravity "$GRAVITY"); fi if [ ! -f "$IN_FILE" ]; then echo "The input file does not exist: '$IN_FILE'"; exit; fi if [ "$OUTFILE" == "" ]; then OUTFILE=${IN_FILE%.*}-${IN_FILE#*.}-polaroid.png; fi ARGS=("${ARGS_CAPTION[@]}" -thumbnail 480x480 -border 5x5 -pointsize 60 "${ARGS_GRAVITY[@]}" +polaroid -thumbnail 120x120) echo convert "${ARGS[@]}" "$IN_FILE" "$OUTFILE"; convert "${ARGS[@]}" "$IN_FILE" "$OUTFILE" 

I hope this will be useful for those looking for a similar solution.

+6
bash
source share
4 answers

You will want to read the entry 050 in the BASH FAQ :

I try to put the command in a variable, but complex cases always fail!

Variables store data. Functions contain code. Do not put code inside variables! There are many situations where people try to drag teams or team arguments into variables and then run them. Each case must be handled separately.

...

  1. I am building a team based on information that is known only at runtime

The root of the problem described above is that you need a way to keep each argument as a separate word, even if that argument contains spaces. The quotes will not do this, but there will be an array. (We saw a little in the previous section, where we built an array of addrs on the fly.)

If you need to create a command dynamically, put each argument in a separate element of the array. A shell with arrays (e.g. Bash) makes this a lot easier. POSIX sh has no arrays, so the closest thing you can do is create a list of elements in positional parameters. Here is the POSIX sh version of the sendto function from the previous section:

+10
source share

Use an array like this:

 #!/bin/bash # ^^^ - note the shebang line explicitly using bash, not /bin/sh CAPTION="Is this Cute?" # The actual value will be tacked from the parameter of this bash. IN_FILE="resources/puppy.png" OUTFILE="resources/puppy_polaroid.png" extra_args=( ) if [[ $CAPTION ]] ; then extra_args+=( -caption "$1" ) fi convert "${extra_args[@]}" "$INFILE" "$OUTFILE" 

This design assumes that you are potentially going to add numerous additional arguments. Note that += not supported on some older versions of bash that are still present on systems deployed in the field (in particular, RHEL4). For such older versions, you may need to write extra_args=( "${extra_args[@]}" -caption "$1" ) to add to the array.

+2
source share

Enabling feedback around $COMMAND in the last line causes the script to try to execute the output of the command, not the command itself.

 $ c='echo hi' $ `$c` hi: command not found 

This will work:

 if [[ "$CAPTION" != "" ]] then convert -caption "$CAPTION" "$IN_FILE" "$OUTFILE" else convert "$IN_FILE" "$OUTFILE" fi 
+1
source share
 CAPTION="$1" IN_FILE="resources/puppy.png" OUTFILE="resources/puppy_polaroid.png" case "$CAPTION" in "" ) CAPTION="-caption ''";; * ) CAPTION='-caption "$CAPTION"';; esac convert $CAPTION "$IN_FILE" "$OUTFILE" 
-one
source share

All Articles