How to Run Script Commands from Variables

Bash script - variable content as a command to run

You just need to do:

#!/bin/bash
count=$(cat last_queries.txt | wc -l)
$(perl test.pl test2 $count)

However, if you want to call your Perl command later, and that's why you want to assign it to a variable, then:

#!/bin/bash
count=$(cat last_queries.txt | wc -l)
var="perl test.pl test2 $count" # You need double quotes to get your $count value substituted.

...stuff...

eval $var

As per Bash's help:

~$ help eval
eval: eval [arg ...]
Execute arguments as a shell command.

Combine ARGs into a single string, use the result as input to the shell,
and execute the resulting commands.

Exit Status:
Returns exit status of command or success if command is null.

How to run script commands from variables?

You're demonstrating the difference between the shell and the kernel.

"ls -l" is executable by the system execve() call. You can man execve for details, but that's probably too much detail for you.

"ls -l | grep e" needs shell interpretation to set up the pipe. Without using a shell, the '|' character is just passed into execve() as an argument to ls. This is why you see the "No such file or directory" errors.

Solution:

cmd="ls -l | grep e"
bash -c "$cmd"

How can I execute a command stored in a variable?

Unix shells operate a series of transformations on each line of input before executing them. For most shells it looks something like this (taken from the Bash man page):

  • initial word splitting
  • brace expansion
  • tilde expansion
  • parameter, variable and arithmetic expansion
  • command substitution
  • secondary word splitting
  • path expansion (aka globbing)
  • quote removal

Using $cmd directly gets it replaced by your command during the parameter expansion phase, and it then undergoes all following transformations.

Using eval "$cmd" does nothing until the quote removal phase, where $cmd is returned as is, and passed as a parameter to eval, whose function is to run the whole chain again before executing.

So basically, they're the same in most cases and differ when your command makes use of the transformation steps up to parameter expansion. For example, using brace expansion:

$ cmd="echo foo{bar,baz}"

$ $cmd
foo{bar,baz}

$ eval "$cmd"
foobar foobaz

Bash: executing a command stored in a variable

Use eval to execute the command stored in the variable:

echo 'echo "" > tmp' | while read cmd; do eval "$cmd" ; done

The value of cmd will be echo "" > tmp. Then when Bash resolves the parameter substitution as a command, the part "" > tmp will be the string arguments of echo, not be recognized as >(redirection). So it will just output the arguments part.

The same as: $(echo 'echo "" > tmp')

How do I set a variable to the output of a command in Bash?

In addition to backticks `command`, command substitution can be done with $(command) or "$(command)", which I find easier to read, and allows for nesting.

OUTPUT=$(ls -1)
echo "${OUTPUT}"

MULTILINE=$(ls \
-1)
echo "${MULTILINE}"

Quoting (") does matter to preserve multi-line variable values; it is optional on the right-hand side of an assignment, as word splitting is not performed, so OUTPUT=$(ls -1) would work fine.

How can I store a command in a variable in a shell script?

Use eval:

x="ls | wc"
eval "$x"
y=$(eval "$x")
echo "$y"

How to execute a bash command stored as a string with quotes and asterisk

Have you tried:

eval $cmd

For the follow-on question of how to escape * since it has special meaning when it's naked or in double quoted strings: use single quotes.

MYSQL='mysql AMORE -u username -ppassword -h localhost -e'
QUERY="SELECT "'*'" FROM amoreconfig" ;# <-- "double"'single'"double"
eval $MYSQL "'$QUERY'"

Bonus: It also reads nice: eval mysql query ;-)

How do I run a bash script and set variables?

To set environment variables that will be inherited by the script process, put the assignments at the beginning:

dbname="hello" dbuser="admin" bash wp.sh

Bash: execute content of variable including pipe

Using eval is not recommended here. It can lead to unexpected results, especially when variables can be read from untrusted sources (See BashFAQ/048 - Eval command and security issues.

You can solve this in a simple way by defining and calling a function as below

ps_cmd() {
ps aux | grep -v grep
}

and use it in the script as

output="$(ps_cmd)"
echo "$output"

Also a good read would be to see why storing commands in a variable is not a good idea and has a lot of potential pitfalls - BashFAQ/050 - I'm trying to put a command in a variable, but the complex cases always fail!

Short way to run command if variable is set

Instead of relying on the value of the variable to have an executable value (and a value that you want to be executed), define a function that simply checks if the value is set.

debug () [[ -v DEBUG ]]

debug && echo "Hello"

If DEBUG is set at all, even to the empty string, debug will succeed and the following command executes.

If DEBUG is not set and you want your script to run the debug commands, simply invoke it as

DEBUG= ./myscript

If DEBUG is set, you can unset it first.

unset DEBUG
./myscript

If the value of DEBUG really matters for whatever reason, then you can just test that it has a non-empty value instead of using -v:

debug () [[ -n $DEBUG ]]

To run your script in debug mode, pick an arbitrary non-empty value

DEBUG=1 ./myscript

To run your script in "real" mode even if DEBUG is current set in your environment, use

DEBUG= ./myscript


Related Topics



Leave a reply



Submit