Calling one Bash script from another Script passing it arguments with quotes and spaces Calling one Bash script from another Script passing it arguments with quotes and spaces bash bash

Calling one Bash script from another Script passing it arguments with quotes and spaces


Quote your args in Testscript 1:

echo "TestScript1 Arguments:"echo "$1"echo "$2"echo "$#"./testscript2 "$1" "$2"


You need to use : "$@" (WITH the quotes) or "${@}" (same, but also telling the shell where the variable name starts and ends).

(and do NOT use : $@, or "$*", or $*).

ex:

#testscript1:echo "TestScript1 Arguments:"for an_arg in "$@" ; do   echo "${an_arg}"doneecho "nb of args: $#"./testscript2 "$@"   #invokes testscript2 with the same arguments we received

I'm not sure I understood your other requirement ( you want to invoke './testscript2' in single quotes?) so here are 2 wild guesses (changing the last line above) :

'./testscript2' "$@"  #only makes sense if "/path/to/testscript2" containes spaces?./testscript2 '"some thing" "another"' "$var" "$var2"  #3 args to testscript2

Please give me the exact thing you are trying to do

edit: after his comment saying he attempts tesscript1 "$1" "$2" "$3" "$4" "$5" "$6" to run : salt 'remote host' cmd.run './testscript2 $1 $2 $3 $4 $5 $6'

You have many levels of intermediate: testscript1 on host 1, needs to run "salt", and give it a string launching "testscrit2" with arguments in quotes...

You could maybe "simplify" by having:

#testscript1#we receive args, we generate a custom script simulating 'testscript2 "$@"'theargs="'$1'"shiftfor i in "$@" ; do   theargs="${theargs} '$i'"donesalt 'remote host' cmd.run "./testscript2 ${theargs}"

if THAt doesn't work, then instead of running "testscript2 ${theargs}", replace THE LAST LINE above by

echo "./testscript2 ${theargs}" >/tmp/runtestscript2.$$  #generate custom script locally ($$ is current pid in bash/sh/...)scp /tmp/runtestscript2.$$ user@remotehost:/tmp/runtestscript2.$$ #copy it to remotehostsalt 'remotehost' cmd.run "./runtestscript2.$$" #the args are inside the custom script!ssh user@remotehost "rm /tmp/runtestscript2.$$" #delete the remote onerm /tmp/runtestscript2.$$ #and the local one


You could do the following to parse all arguments:

Note the use of /bin/bash

testscript1:

#!/bin/bashecho "TestScript1 Arguments:"echo "$1"echo "$2"echo "$#"# Build PARAMS to be a list of arguments# Each wrapped in quotes and# any existing quotes escapes with \for var in "$@"do    PARAMS="$PARAMS \"${var//\"/\\\"}\""done# Call the second script with eval, also passing an extra parameter.eval ./testscript2 "ExtraParam" $PARAMS

testscript2:

#!/bin/bashecho "TestScript2 Arguments received from TestScript1:"echo "$1"echo "$2"echo "$3"echo "$#"

Then when you execute the following:

./testscript1 "Firstname Lastname" testmail@domain.com  

The output will be:

TestScript1 Arguments:Firstname Lastnametestmail@domain.com2TestScript2 Arguments received from TestScript1:ExtraParamFirstname Lastnametestmail@domain.com3

By building the PARAMS in this way using \"${var//\"/\\\"}\"" it allows for the script to behave correctly even if called with quotes in the arguments such as follows:

./testscript1 "Firstname's Last\"name" testmail@domain.com  

Output will be:

TestScript1 Arguments:Firstname's Last"nametestmail@domain.com2TestScript2 Arguments received from TestScript1:ExtraParamFirstname's Last"nametestmail@domain.com3

All quotes and spaces are passed from one script to the other correctly.

If you don't want all the arguments passed, miss out the for loop and just use eval with the relevant arguments.

For example:

eval ./testscript2 "\"${1//\"/\\\"}\"" "Test1" "Test2" 

${1... means the 1st argument, use ${2... for the 2nd etc.

This will result in:

TestScript1 Arguments:Firstname's Last"nametestmail@domain.com2TestScript2 Arguments received from TestScript1:Firstname's Last"nameTest1Test23

If you're sure you'll never get quotes in the argument, then don't use "\"${1//\"/\\\"}\"" just use "$1".