Passing varibles as a string argument ?

For example

test.sh:

test="teststring"
cmd=$1 
$cmd 

For some reason I'm NOT seeing "teststring" when I type: ./test.sh "echo $test"

Any ideas on how to get around this?

I've tried commands like:

./test.sh "echo $($test)"
./test.sh "echo '$test'"

And many variations to no avail.

Change your script:

test="teststring"
 cmd=$1 
eval $cmd

And invoke it with:

./test.sh "echo \$test"

This passes the string echo $test into the script (without expanding the variable on the command line). The eval in the script causes $cmd to be expanded to echo $test which then expands to echo teststring before it is executed.

1 Like

Perfect, thanks.

Although this construct will work, I would like to suggest you redesign the script. The reason is security vulnerability that you are implicitly building into it. What if the user runs the script with "./test.sh rm -r /" (don't run this!)? Your script would execute that command obediently.
You'd be better off to stay away from 'eval', if you cannot have total control of the argument of 'eval'. In other words, invoking eval on a user-defined input can be dangerous.

You might want to hard-code the command into your script, and then just pass the argument to it, something like:

#!/bin/bash
arg=$1
#do whatever
echo $arg

and then call the script with

./test.sh "$var"

If you can show us a bigger picture of what you are trying to accomplish, we could suggest a better way to implement it.

Thanks for pointing that out.

If the user tried to delete the root directory, wouldn't it stop them because they aren't root?

Basically, I've made a bash script that runs commands passed to it on multiple devices.

Then, for scheduled tasks, I'm having the script be called with commands and variables to facilitate easier management.

The tricky part is making it so a user can do something like ./send-commands devicelist "ssh $username@$device" which I've fixed using the eval method.

The user doesn't have to specify the command (ssh), if you hard-code it into the script. Then the user just does

./send-commands devicelist $username $device

That way, you can avoid 'eval'.

You can find some examples, where using 'eval' is fine, in the ABS guide:
Advanced Bash-Scripting Guide

but you can also read there (and many other sources):

The command wont always be ssh. I want to keep the script as simple and compact as possible.