Bash: space in variable value later used as parameter

前端 未结 4 2009
佛祖请我去吃肉
佛祖请我去吃肉 2020-12-18 03:52

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

相关标签:
4条回答
  • 2020-12-18 04:34
    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"
    
    0 讨论(0)
  • 2020-12-18 04:36

    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
    
    0 讨论(0)
  • 2020-12-18 04:44

    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:

    0 讨论(0)
  • 2020-12-18 04:54

    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.

    0 讨论(0)
提交回复
热议问题