I was wondering: When I e.g. call
list=$(ps -ax)
is ps -ax executed once and I can read the value multiple times or is the command executed e
To cite the bash manpage:
Command Substitution
Command substitution allows the output of a com-
mand to replace the command name. There are two forms:
$(command)
or
`command`
So the output of the command is stored, not the command itself.
If you want to store a command that is evaluated each time, you need to use eval
:
#!/bin/bash
command="date"
startTime=$(date)
for i in `seq 1 4`
do
echo "$i: $startTime - " $(eval $command)
sleep 1
done
Solution is, that the result is stored. To test that, I used the following script
#!/bin/sh
myTime=$(date)
for a in 1 2 3 4
do
echo 'Stored command: '$myTime
echo 'Fresh command: '$(date)
sleep 2
done
Result looks like this:
Stored commandTue Sep 29 17:39:44 +02 2020
Fresh commandTue Sep 29 17:39:44 +02 2020
Stored commandTue Sep 29 17:39:44 +02 2020
Fresh commandTue Sep 29 17:39:46 +02 2020
Stored commandTue Sep 29 17:39:44 +02 2020
Fresh commandTue Sep 29 17:39:48 +02 2020
Stored commandTue Sep 29 17:39:44 +02 2020
Fresh commandTue Sep 29 17:39:50 +02 2020
Feel free to add missing tags; not sure about how to make stuff like $() most search engine friendly
POSIX sh guarantees that the command will not be re-executed, see below.
Be careful about concluding things about POSIX sh through empirical tests. For example, if you time sleep 60 | true
, you'd find that bash, ksh, zsh and dash all take 60 seconds. However, POSIX sh still allows it to finish immediately.
Spec for $():
The shell shall expand the command substitution by executing command in a subshell environment (see Shell Execution Environment) and replacing the command substitution (the text of command plus the enclosing "$()" or backquotes) with the standard output of the command.
and when it's applied:
When a given simple command is required to be executed [...] the following expansions, assignments, and redirections shall all be performed from the beginning of the command text to the end:
[...]
- Each variable assignment shall be expanded for tilde expansion, parameter expansion, command substitution, arithmetic expansion, and quote removal prior to assigning the value.
[...]
Variable assignments shall be performed as follows:
If no command name results, variable assignments shall affect the current execution environment.
Since $()
is replaced with the text of the command, and this happens before the variable is assigned, the command is guaranteed not to be re-executed in a conforming POSIX sh implementation.