How can I split a command over multiple lines in the shell, when the command is part of an if
statement?
This works:
if ! fab --fabfile=.deploy/fabfile.py --forward-agent --disable-known-hosts deploy:$target; then rc=1 fi
This doesn't work:
# does not work: if ! fab --fabfile=.deploy/fabfile.py \ --forward-agent \ --disable-known-hosts deploy:$target; then rc=1 fi
Instead of the whole command executing, I get:
./script.sh: line 73: --forward-agent: command not found
More importantly, what is missing from my understanding of Bash that will help me understand this and similar issues in the future?
To split long commands into readable commands that span multiple lines, we need to use the backslash character (\). The backslash character instructs bash to read the commands that follow line by line until it encounters an EOL.
To use multiple conditions in one if-else block, then elif keyword is used in shell. If expression1 is true then it executes statement 1 and 2, and this process continues. If none of the condition is true then it processes else part.
If you want to break up a command so that it fits on more than one line, use a backslash (\) as the last character on the line.
The line-continuation will fail if you have whitespace (spaces or tab characters¹) after the backslash and before the newline. With no such whitespace, your example works fine for me:
$ cat test.sh if ! fab --fabfile=.deploy/fabfile.py \ --forward-agent \ --disable-known-hosts deploy:$target; then echo failed else echo succeeded fi $ alias fab=true; . ./test.sh succeeded $ alias fab=false; . ./test.sh failed
Some detail promoted from the comments: the line-continuation backslash in the shell is not really a special case; it is simply an instance of the general rule that a backslash "quotes" the immediately-following character, preventing any special treatment it would normally be subject to. In this case, the next character is a newline, and the special treatment being prevented is terminating the command. Normally, a quoted character winds up included literally in the command; a backslashed newline is instead deleted entirely. But otherwise, the mechanism is the same. Most importantly, the backslash only quotes the immediately-following character; if that character is a space or tab, you just get a literal space or tab; the backslash will have no effect on a subsequent newline.
¹ or carriage returns, for that matter, as Czechnology points out. The POSIX shell does not get along with Windows-formatted text files, not even in WSL. Or Cygwin, but at least their Bash port has added an igncr
option that you can set -o
to make it carriage-return-tolerant.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With