LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   is it possible to execute more than one command from inside a variable in BASH? (https://www.linuxquestions.org/questions/programming-9/is-it-possible-to-execute-more-than-one-command-from-inside-a-variable-in-bash-910346/)

lityit 10-26-2011 05:40 PM

is it possible to execute more than one command from inside a variable in BASH?
 
For example if i want to execute 3 commands and i want to store all 3 of these commands in a variable like so:

Code:

variable="echo hello && mkdir uhoh && echo goodbye"
I would get this when trying to execute it:
Code:

$variable
hello && mkdir uhoh && echo goodbye

It only pays attention to the first command and echo's the rest. But what if I want it to execute all three commands, is there any way to do this?

lyle_s 10-26-2011 06:23 PM

Quote:

Originally Posted by lityit (Post 4509236)
For example if i want to execute 3 commands and i want to store all 3 of these commands in a variable like so:

Code:

variable="echo hello && mkdir uhoh && echo goodbye"
I would get this when trying to execute it:
Code:

$variable
hello && mkdir uhoh && echo goodbye

It only pays attention to the first command and echo's the rest. But what if I want it to execute all three commands, is there any way to do this?

Yes, you need to use eval:
Code:

variable="echo hello && mkdir uhoh && echo goodbye"

eval "$variable"

I've found this useful when you want to echo the command being run before running it:
Code:

#!/bin/sh

some_command="ls -l /"

echo "Running $some_command"

eval "$some_command"

It keeps you from having to type in the command twice, and if you need to change it you need only change it in one place.

Lyle.

lityit 10-26-2011 07:16 PM

Quote:

Originally Posted by lyle_s (Post 4509260)
Yes, you need to use eval:
Code:

variable="echo hello && mkdir uhoh && echo goodbye"

eval "$variable"

I've found this useful when you want to echo the command being run before running it:
Code:

#!/bin/sh

some_command="ls -l /"

echo "Running $some_command"

eval "$some_command"

It keeps you from having to type in the command twice, and if you need to change it you need only change it in one place.

Lyle.

thanks

grail 10-26-2011 11:40 PM

Personally I would try and create a function instead of using a variable as eval has its own little issues and the eventual need to escape all in sundry
becomes a real pain.

Nominal Animal 10-27-2011 12:06 AM

I fully agree with grail, especially since both Bash and POSIX shells allow you to define a function practically anywhere. You can do things like
Code:

setfoo () {
    if [ "$1" = "y" ]; then
        foo () {
            echo "foo: yes"
        }
    else
        foo () {
            echo "foo: no"
        }
    fi
}

so that for example
Code:

setfoo y
foo
setfoo n
foo

will output
Code:

foo: yes
foo: no

If you want a niftier example, define function setfoo like this:
Code:

setfoo () {
    eval "foo () {
        echo \"$*:\" \"\$@\"
    }"
}

The eval there is needed since we want $* from the outer function. To make sure "$@" is not evaluated within the eval, we escape it to "\$@".

Then, running
Code:

setfoo a b c
foo 1 2 3
foo 3 2 1

setfoo d e f
foo 4 5 6
foo 6 5 4

will output
Code:

a b c: 1 2 3
a b c: 3 2 1

d e f: 4 5 6
d e f: 6 5 4


David the H. 10-27-2011 10:29 AM

Variables are designed for storing data, not code. So in general you shouldn't put commands in variables at all. As the others have pointed out, storing code is what functions are designed for.

http://mywiki.wooledge.org/BashFAQ/050

At best variables can, and perhaps even should, be used to hold some of the arguments to a command. And even then you should use an array to store them if you have multiple options to string together.

Edit: Oh, and see here for details on the security implications of eval:

http://mywiki.wooledge.org/BashFAQ/048

90% of the time there are better ways to do what you want anyway.


All times are GMT -5. The time now is 03:09 PM.