2

I saw script where the condition in an if statement used a $ and I don't understand why?

if $( ssh user@host " test -e file  " ); then 
   echo "File is there"
else
   echo "We don't that file on that host"
fi
1
  • 2
    To be very clear, by the way -- this is bad practice (and a serious security issue, even, since it means that anything the server sends back on the stdout of the test command will be run locally as a command); the script shouldn't be written that way. Jun 19, 2015 at 20:17

3 Answers 3

12

$(...) is a command substitution. The shell runs the enclosed command, and the expression is replaced by the command's standard output.

Generally, this would produce an error if the replacement text did not name a command that the shell could then run. However, test produces no output, so the result is an empty string that the shell "skips". For example, consider what happens if you run

if $( ssh user@host " echo foo " ); then 
   echo "File is there"
else
   echo "We don't that file on that host"
fi

The given code is correctly written without the unnecessary command substitution; the only thing the if statement needs is the exit status of the command.

if ssh user@host "test -e file"; then 
   echo "File is there"
else
   echo "We don't that file on that host"
fi
1
  • 3
    +1. Note that test produces no output, but if the login shell of the remote user is csh/tcsh/bash, then the ~/.<shell>rc file is interpreted and may produce some output. In any case, I would drop the more in your is more correctly written. Doing if $(ssh user@host "test -e file") doesn't make any sense. And if user's account is compromised on host (or you don't trust him), that has security implications. Jun 19, 2015 at 13:00
6

The $( ... ) construct executes a command and returns the exit status of the command along with its output as a string. It's a more modern version of backticks `...`.

It can be used like this: my_id=$(id)

The snippet you have posted is broken code, though. It uses the result of ssh user@host "test -f file", which appears to return a boolean based on the existence of the file on the remote host. Unfortunately it fails to take into account that the ssh itself might fail:

if $(ssh -q localhost true); then echo YES; else echo NO; fi
YES

if $(ssh -q localhost false); then echo YES; else echo NO; fi
NO

if $(ssh -q nowhere true); then echo YES; else echo NO; fi
ssh: Could not resolve hostname nowhere: Name or service not known
NO

Perhaps this is intended behaviour, but I suspect not.

Furthermore, the $( ... ) is redundant, and the condition can be better expressed directly:

if ssh -q user@host "test -e file"; then 
   echo "File is there"
else
   echo "We don't [see] that file on that host [or the ssh failed]"
fi
3

The $(command) is called command substitution (see the POSIX specs here and the bash manual here). It is a way of running a command and passing its output to another. It is equivalent to `command` but the $(...) syntax is preferred since it is easier to nest commands and results in more readable code.

For example:

$ echo $(echo "bar")
bar

The command above passed the output of echo "bar" (which is bar) to the outer echo.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.