Question

I made two test bash scripts on Linux to make the problem clear.

TestScript1 looks like:
    echo "TestScript1 Arguments:"
    echo "$1"
    echo "$2"
    echo "$#"
    ./testscript2 $1 $2
TestScript2 looks like:
    echo "TestScript2 Arguments received from TestScript1:"
    echo "$1"
    echo "$2"
    echo "$#"
When i execute testscript1 in the following way:
    ./testscript1 "Firstname Lastname" testmail@domain.com  
The desired Output should be:
    TestScript1 Arguments:  
    Firstname Lastname  
    testmail@domain.com  
    2
    TestScript2 Arguments received from TestScript1:  
    Firstname Lastname  
    testmail@domain.com  
    2  
But the actual output is:
    TestScript1 Arguments:  
    Firstname Lastname  
    testmail@domain.com  
    2
    TestScript2 Arguments received from TestScript1:  
    Firstname
    Lastname      
    3  

How do i solve this problem? I want to get the desired output instead of the actual output.

Was it helpful?

Solution

Quote your args in Testscript 1:

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

OTHER TIPS

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}"
done
echo "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'"
shift
for i in "$@" ; do
   theargs="${theargs} '$i'"
done

salt '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 remotehost
salt 'remotehost' cmd.run "./runtestscript2.$$" #the args are inside the custom script!
ssh user@remotehost "rm /tmp/runtestscript2.$$" #delete the remote one
rm /tmp/runtestscript2.$$ #and the local one

You could do the following to parse all arguments:

Note the use of /bin/bash

testscript1:

#!/bin/bash

echo "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/bash
echo "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 Lastname
testmail@domain.com
2
TestScript2 Arguments received from TestScript1:
ExtraParam
Firstname Lastname
testmail@domain.com
3

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"name
testmail@domain.com
2
TestScript2 Arguments received from TestScript1:
ExtraParam
Firstname's Last"name
testmail@domain.com
3

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"name
testmail@domain.com
2
TestScript2 Arguments received from TestScript1:
Firstname's Last"name
Test1
Test2
3

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

I found following program works for me

test1.sh 
a=xxx
test2.sh $a

in test2.sh you use $1 to refer variable a in test1.sh

echo $1

The output would be xxx

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top