-2

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 every time I call $list

  • Related: https://unix.stackexchange.com/questions/440088/what-is-command-substitution-in-a-shell – Pranav Hosangadi Sep 29 '20 at 16:06
  • 1
    Why ask a question here? You could answer this yourself with three lines: `time=$(date +%s); echo "$time"; sleep 1; echo "$time"` – Charles Duffy Sep 29 '20 at 16:09
  • @CharlesDuffy that's exactly what I did, see below. Plan was to answer the own questions so that others find this solution. No Idea, why this was not marked as resolved O_o – Human_BetaRelease Sep 29 '20 at 16:26
  • There's a timeout before self-answers are allowed to be accepted, but you should be able to accept it eventually. That said, we get a lot of questions asked based on people expecting the contrary behavior, so there are certainly duplicates already in the knowledgebase. – Charles Duffy Sep 29 '20 at 16:32
  • OTOH, it makes more sense to close _those_ as a duplicate of _this_, being clearly-asked as it is. – Charles Duffy Sep 29 '20 at 16:34

3 Answers3

1

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

1

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:

[...]

  1. 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.

that other guy
  • 116,971
  • 11
  • 170
  • 194
0

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
Molith
  • 1
  • 2
  • Your answer is about bash, question is about POSIX sh. (adjusted title to make it more clear) I don't see a duplicate – Human_BetaRelease Sep 29 '20 at 16:23
  • The original question didn't indicate anything about POSIX, apart from the tag. OTOH the cited bash man page didn't mark that behaviour as bash specific. Additionally, my answer at least adds what needs to be done, if you don't want the result being stored, but to execute the stored command each time. – Molith Sep 29 '20 at 20:03