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
How to Realize a Diff Function
How to Expand Relative Paths in Shell Script
How to Ignore Some Differences in Diff Command
Parallel Make: Set -J8 as The Default Option
How to Restart a Service If Its Dependent Service Is Restarted
Using Mkdir -M -P and Chown Together Correctly
Tar: Error Is Not Recoverable: Exiting Now
How to Move a Relative Symbolic Link
Fast String Search in a Very Large File
Asp.Net Core Environment Variable Colon in Linux
How to Output Return Code in Shell
Bash Script to Find The Frequency of Every Letter in a File
Concatenating Two String Variables in Bash Appending Newline