Find the answer to your Linux question:
Results 1 to 5 of 5
Like Tree1Likes
  • 1 Post By alf55
I have three scripts, that are called one after another. So the user calls the first one, and then the first script will perform a call to the second one, ...
Enjoy an ad free experience by logging in. Not a member yet? Register.
  1. #1
    Just Joined!
    Join Date
    Apr 2013
    Posts
    5

    Passing arguments with spaces/quotes through a few scripts


    I have three scripts, that are called one after another. So the user calls the first one, and then the first script will perform a call to the second one, and the second will call the third.

    Code:
    script_1.sh --> script_2 .sh --> script_3.sh
    The challenge is, I have to pass a list of flags from user command line up to the third script. The scripts are using "getopts" to iterate through the input arguments.

    The arguments will look something like: "flag_1=true flag_2=false flag_3=value flag_4=another.value"

    The user calls the first script as follows:
    Code:
    script_1.sh -a argument1 -b argument2 -c "flag_1=true flag_2=false flag_3=value flag_4=another.value"
    The script then looks if the "-c" flag is not empty, and passes the values to script_2.sh.

    The problem appear when assigning the value for "-c" flag to a variable in the second script.
    Basically, what happens is that:
    1. If I print all the arguments the script received it prints:
    Code:
     [...] -c "flag_1=true flag_2=false flag_3=value flag_4=another.value"
    2. But after assigning the flag value to a variable, and printing the content, it only returns the first combination in the list.

    Code in second script:

    Code:
    ARG1=""
    ARG2=""
    FLAGS=""
    
    while getopts "a:b:c:" arg
      do
      case "$arg" in
      a) ARG1=$OPTARG;;
      b) ARG2=$OPTARG;;
      c) FLAGS="$OPTARG";;
      *) echo "Invalid option $arg" ;;
      ?) usage
      esac
    done
    Printing $FLAGS returns:
    Code:
    "flag_1=true
    I've tried changing to single quotes but this is not working either.

  2. #2
    Linux Enthusiast
    Join Date
    Jan 2005
    Location
    Saint Paul, MN
    Posts
    668
    You need to use double quotes (") around the variable references. By having a script that does not do this, is a sign of not understanding that without quotes items are broken on "white space" (space, tab, ff, cr, lf, etc). When arguments are paths or file names, it is really hard to write a script that would handle all legal paths and file names as the only characters that are not legal in this are NIL (chr(0)) and slash (/). But a lot of those valid path and strings will be hard to enter and will not copy onto a vfat, ntfs, etc (or a CIFS share hosted on a windows machine as windows will not allow them). Windows does not allow the double quote in a path or file name as they use it to quote the names and one in the name would mess that up.

    Code:
    Since the command is tokenized by whitespace, any spaces in the command that are not separators must be quoted. Bash has three styles of quoting.
    Quote Style 	Definition and sample usage
    Quote mark
    Double quote mark 	The use of the normal English quote mark (") can be used to quote the whole argument.
    
       "this is a single argument"
    
    Advantage here is the the expansion of variables will occur.
    
        my_var='13'
        echo "this is an example ${my_var} is expanded"
    
    Single quote mark 	Use the single quote mark which is the English apostrophe (') to quote the whole argument.
    
       'this is a single argument'
    
    Advantage here is the the expansion of variables will not occur.
    
        my_var='13'
        echo 'this is an example ${my_var} is not expanded'
    
    single character 	Any single character can be quotes by preceding it with a back-slash (\) character.
    
       this\ is\ a\ single\ argument
    
    Advantage here is the great control held by the user.
    
        my_var='13'
        echo this\ is\ an\ example\ \${my_var}\ is\ not\ expanded\ while\ ${my_var}\ is\ expanded
    
    Disadvantage here is that it can become very hard to read.

  3. #3
    Just Joined!
    Join Date
    Apr 2013
    Posts
    5
    The problem, in my particular case were not the quotes. As you can see in my examples, I was using them. the problem seems to pe the `echo` command I used to pass the value of the flag.

    So, after calling the first script with something like:

    Code:
    script_1.sh -a argument1 -b argument2 -c "flag_1=true flag_2=false flag_3=value flag_4=another.value"
    Script1 processes the arguments with below sequence:

    Code:
    ARG1=""
    ARG2=""
    FLAGS=""
    
    while getopts "a:b:c:" arg
      do
      case "$arg" in
      a) ARG1=$OPTARG;;
      b) ARG2=$OPTARG;;
      c) FLAGS=$OPTARG;;
      *) echo "Invalid option $arg" ;;
      ?) usage
      esac
    done
    Next, the value is assigned to $FLAGS.
    And then, the first script was calling the second one with a line like the following:

    Code:
    script_2.sh -a ARG1 -b ARG2 `if [ -z "$FLAGS" ]; then echo "-c $FLAGS"; fi`
    Doing this seems to mess up the parameters list transmitted into the second script. And even if, by checking the whole list of received arguments in the second script, I can see that the entire list was transmitted... still, only the first key/value pair gets set in the right place, in the second script.

  4. $spacer_open
    $spacer_close
  5. #4
    Linux Newbie
    Join Date
    Nov 2012
    Posts
    230
    that seems smart, but you shouldn't try to be smart with the shell
    K.I.S.S. :
    Code:
    if test -n "$FLAGS"; then script_2 -a ARG1 -b ARG -c "$FLAGS"; fi

  6. #5
    Linux Enthusiast
    Join Date
    Jan 2005
    Location
    Saint Paul, MN
    Posts
    668
    You need quotes when ever passing arguments...

    script1 has the code:
    Code:
    #!/bin/bash
    #
    
    printf "\n ------------- entering script1 -------------\n\n"
    
    a_arg=""
    b_arg=""
    c_arg=""
    
    while [ $# -gt 0 ] ; do
        case "${1}" in
            -a) a_arg="${2}" ; shift ; shift ;;
            -b) b_arg="${2}" ; shift ; shift ;;
            -c) c_arg="${2}" ; shift ; shift ;;
            *)  shift ;;
        esac
    done
    
    printf "a_arg is '%s'\n" "${a_arg}"
    printf "b_arg is '%s'\n" "${b_arg}"
    printf "c_arg is '%s'\n" "${c_arg}"
    
    
    if [ "${c_arg}" != "" ] ; then
        ./script2 -a "${a_arg}" -b "${b_arg}" -c "${c_arg}"
    else
        ./script2 -a "${a_arg}" -b "${b_arg}"
    fi
    
    printf "\n ------------- leaving  script1 -------------\n\n"
    script3 has the code:
    Code:
    #!/bin/bash
    #
    
    printf "\n ------------- entering script2 -------------\n\n"
    
    a_arg=""
    b_arg=""
    c_arg=""
    
    while [ $# -gt 0 ] ; do
        case "${1}" in
            -a) a_arg="${2}" ; shift ; shift ;;
            -b) b_arg="${2}" ; shift ; shift ;;
            -c) c_arg="${2}" ; shift ; shift ;;
            ?)  echo "show usage here" ; exit 1 ;;
            *)  echo "INvalid option '${1}'" ; shift ;;
        esac
    done
    
    printf "a_arg is '%s'\n" "${a_arg}"
    printf "b_arg is '%s'\n" "${b_arg}"
    printf "c_arg is '%s'\n" "${c_arg}"
    
    
    if [ "${c_arg}" != "" ] ; then
        ./script3 -a "${a_arg}" -b "${b_arg}" -c "${c_arg}"
    else
        ./script3 -a "${a_arg}" -b "${b_arg}"
    fi
    
    printf "\n ------------- leaving  script2 -------------\n\n"
    script3 has the code:
    Code:
    #!/bin/bash
    #
    
    printf "\n ------------- entering script3 -------------\n\n"
    
    a_arg=""
    b_arg=""
    c_arg=""
    
    while [ $# -gt 0 ] ; do
        case "${1}" in
            -a) a_arg="${2}" ; shift ; shift ;;
            -b) b_arg="${2}" ; shift ; shift ;;
            -c) c_arg="${2}" ; shift ; shift ;;
            ?)  echo "show usage here" ; exit 1 ;;
            *)  echo "INvalid option '${1}'" ; shift ;;
        esac
    done
    
    printf "a_arg is '%s'\n" "${a_arg}"
    printf "b_arg is '%s'\n" "${b_arg}"
    printf "c_arg is '%s'\n" "${c_arg}"
    
    
    printf "\n ------------- leaving  script3 -------------\n\n"

    Then running script1 via:
    Code:
    ./script1 -a argument1 -b argument2 -c "flag_1=true flag_2=false flag_3=value flag_4=another.value"
    Results in the output:
    Code:
    
     ------------- entering script1 -------------
    
    a_arg is 'argument1'
    b_arg is 'argument2'
    c_arg is 'flag_1=true flag_2=false flag_3=value flag_4=another.value'
    
     ------------- entering script2 -------------
    
    a_arg is 'argument1'
    b_arg is 'argument2'
    c_arg is 'flag_1=true flag_2=false flag_3=value flag_4=another.value'
    
     ------------- entering script3 -------------
    
    a_arg is 'argument1'
    b_arg is 'argument2'
    c_arg is 'flag_1=true flag_2=false flag_3=value flag_4=another.value'
    
     ------------- leaving  script3 -------------
    
    
     ------------- leaving  script2 -------------
    
    
     ------------- leaving  script1 -------------
    drl likes this.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •