Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I split a shell command over multiple lines when using an IF statement?

Tags:

syntax

sh

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?

like image 319
Dmitry Minkovsky Avatar asked Sep 03 '13 19:09

Dmitry Minkovsky


People also ask

How do I split a shell into multiple lines?

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.

How do you use multiple IF statements in shell script?

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.

When typing at the shell what character can be used to split a command across multiple lines?

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.


1 Answers

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.

like image 71
Mark Reed Avatar answered Sep 24 '22 21:09

Mark Reed