Bash: space in variable value later used as parameter

丶灬走出姿态 提交于 2020-01-28 06:59:24

问题


While writing a bash script to help creating polaroid thumbnail using Imagick's convert commmand. I encounter a problem. Although, I manage to work around with this (actually, because convert is flexible enough), I still want to know how to solve this without such specific workaround.

So basically, the bash script will get a caption value which may contain space. I want to use that caption as parameter of convert. If the caption is empty (''), I will not use the option '-caption' for 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 echoes the value command that can be copied can pasted in a terminal and run. BUT the bash does not run. How I can do this?

NOTE: In case of convert, -caption "" do the job. I know this and currently use this as work around.

Thanks in advance for helps.

EDIT: From the answer, here is the code that work 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 that this will be useful for those seeking similar solution.


回答1:


You'll want to read entry 050 in the BASH FAQ:

I'm trying to put a command in a variable, but the complex cases always fail!

Variables hold data. Functions hold code. Don't put code inside variables! There are many situations in which people try to shove commands, or command arguments, into variables and then run them. Each case needs to be handled separately.

...

  1. I'm constructing a command based on information that is only known at run time

The root of the issue described above is that you need a way to maintain each argument as a separate word, even if that argument contains spaces. Quotes won't do it, but an array will. (We saw a bit of this in the previous section, where we constructed the addrs array on the fly.)

If you need to create a command dynamically, put each argument in a separate element of an array. A shell with arrays (like Bash) makes this much easier. POSIX sh has no arrays, so the closest you can come is to build up a list of elements in the positional parameters. Here's a POSIX sh version of the sendto function from the previous section:




回答2:


Use an array, as so:

#!/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 construct presumes that you're potentially going to be appending numerous extra arguments. Note that += is unsupported in some older versions of bash which are still present on systems deployed in the field (most notably RHEL4). For such older releases it can be necessary to write extra_args=( "${extra_args[@]}" -caption "$1" ) to append to an array.




回答3:


Putting backticks around $COMMAND on the last line causes the script to try to execute the output of the command rather than 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



回答4:


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"


来源:https://stackoverflow.com/questions/2249821/bash-space-in-variable-value-later-used-as-parameter

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!