Bash – How to execute a Bash command and execute two statements on failure

bashcontrol flowshell

I want to execute a Bash command followed by two actions if and only if the test returns an error. I would prefer to solve this task as a one-liner in Bash.

Here are the two forms I have tried:

ssh user@1.2.3.4 "ls /home/somefile" || echo "File does not exist" && exit 1
ssh user@1.2.3.4 "ls /home/somefile" || echo "File does not exist"; exit 1

The meaning is as follows: I want to test the existence of a file on a remote machine (or whatever, just an example), and in the case the first command returns an error, then – and only then – the two following commands (echo /exit) should be executed. The examples above execute the exit 1 statement independent of the return value of the ssh command.

How to rewrite this line so that the echo and the exit commands are only executed if the first (ssh) command fails?

Best Answer

ssh user@1.2.3.4 "ls /home/somefile" || { echo "File does not exist"; exit 1; }

This is called a compound command. From man bash:

   Compound Commands
       A compound command is one of the following:

       (list) list  is  executed in a subshell environment (see COMMAND EXECU‐
              TION ENVIRONMENT below).  Variable assignments and builtin  com‐
              mands  that  affect  the  shell's  environment  do not remain in
              effect after the command completes.  The return  status  is  the
              exit status of list.

       { list; }
              list  is simply executed in the current shell environment.  list
              must be terminated with a newline or semicolon.  This  is  known
              as  a  group  command.   The return status is the exit status of
              list.  Note that unlike the metacharacters ( and ), { and }  are
              reserved words and must occur where a reserved word is permitted
              to be recognized.  Since they do not cause a  word  break,  they
              must  be  separated  from  list  by  whitespace or another shell
              metacharacter.

The () syntax probably wouldn't work in your situation because the commands would be executed in a subshell, and then the exit would just close the subshell.

EDIT: to explain the difference between the parentheses () and the curly braces {}:

The parentheses cause the contained commands to be executed in a subshell. That means that another shell process is spawned which evaluates the commands, and the exit in OP's question would kill this subshell.

The curly braces instead cause the commands to be evaluated in the current shell. Now the exit kills the current shell, which would be for example preferable if you use this line a shell script.

Related Question