Bash - how to avoid command "eval set --" evaluating variables -


i write little bash script managing multiple parallels ssh commands. in order parse arguments use piece of code :

#!/bin/bash  # replace long arguments arg in "$@";     case "$arg" in         --help)           args="${args}-h ";;         --host|-hs)       args="${args}-s ";;         --cmd)            args="${args}-c ";;         *) [[ "${arg:0:1}" == "-" ]] && delim='' || delim="\""            args="${args}${delim}${arg}${delim} ";;     esac done  echo "args before eval : $args" eval set -- $args echo "args after eval  : $args"  while getopts "hs:c:" option;     echo "optarg : $optarg"     case $option in     h)  usage; exit 0;;     s)  servers_array+=("$optarg");;     c)  cmd="$optarg";;     esac done 

so can use instance -s, --host or -hs same result. works fine except 1 thing.

if put variable in argument evaluated.

explanations

./test.sh -s server -c 'echo $hostname' 
  1. cmd should assigned echo $hostname because of eval set cmd in fact assigned echo server1 (the value of variable)

  2. if comment line eval set -- $args cannot use long options (--cmd) cmd assigned echo $hostname expected

is there solution avoid eval set / getopts evaluate variables ? to have same behavior 2. long options available.

examples

with eval set

./test.sh -s server -c 'echo $hostname' args before eval : -s "server" -c "echo $hostname" args after eval  : -s "server" -c "echo $hostname" optarg : server optarg : echo server1 

without eval set (line eval set -- $args commented)

./test.sh -s server -c 'echo $hostname' args before eval : -s "server" -c "echo $hostname" args after eval  : -s "server" -c "echo $hostname" optarg : server optarg : echo $hostname 

as note, eval evil -- , there's no need use here.

#!/bin/bash  # make args array, not string args=( )  # replace long arguments arg;     case "$arg" in         --help)           args+=( -h ) ;;         --host|-hs)       args+=( -s ) ;;         --cmd)            args+=( -c ) ;;         *)                args+=( "$arg" ) ;;     esac done  printf 'args before update : '; printf '%q ' "$@"; echo set -- "${args[@]}" printf 'args after update  : '; printf '%q ' "$@"; echo  while getopts "hs:c:" option;     : "$option" "$optarg"     echo "optarg : $optarg"     case $option in     h)  usage; exit 0;;     s)  servers_array+=("$optarg");;     c)  cmd="$optarg";;     esac done 

that say: when building command line, amend individual items array; can expand array, quoted, without risking either evaluation or undesired behavior via effects of string-splitting, glob expansion, etc.


Comments

Popular posts from this blog

sublimetext3 - what keyboard shortcut is to comment/uncomment for this script tag in sublime -

java - No use of nillable="0" in SOAP Webservice -

ubuntu - Laravel 5.2 quickstart guide gives Not Found Error -