From a syntax parsing point of view, &&, like ;, &, |, ||, separates commands and like in all of them, the following command doesn't have to be on the same line, you can have any number of blank lines (or lines containing only comments) in the interval:
if
cmd1 &&
# also checking this 2-command pipeline:
cmd2 | # piped
# to the command 2 lines below
cmd3
then
echo yes &
echo not no at the same time
wait
fi
For &&, || and | it's good practice to indent-out the following line to remind that its not independent from the previous one.
In all shells, ; and & don't have to be followed by another command. | does.
For && and ||, that depends on the shell.
Most shells require a following command (would error out if followed by the end of the script or of a compound command), zsh does not (and often allows commands to be omitted in positions where other shells don't, such as in { } or if cmd; then else echo else; fi (between then and else) or while echo forever; do done (between do and done)).
Even in zsh though, having && and || not followed by another command is not useful.
$ bash -c '(true &&)'
bash: -c: line 1: syntax error near unexpected token `)'
bash: -c: line 1: `(true &&)'
$ bash -c 'if true && then echo x; fi'
bash: -c: line 1: syntax error near unexpected token `then'
bash: -c: line 1: `if true && then echo x; fi'
$ zsh -c '(true &&)'
$ zsh -c 'if true && then echo x; fi'
x
There are not that many places that require a line-continuation (a \<newline> which is removed unless inside single quotes of here-document with quoted delimiter).
You can usually use a newline in place of a space except in cases where that would change the meaning.
Obviously, you can't replace:
echo foo \
bar
With:
echo foo
bar
As the former runs echo foo bar and the latter echo foo and bar.
But in Korn-like shells, you can do:
if
a=$(
echo "`
uname
`"
) &&
((
2
>
1
))
then
a=(
x
"$((
1
+
1
))"
)
for i
in a b
do
echo "$i"
done
case a
in
(a)
echo a
esac
fi
For instance.
There are a few instances, where newlines are not allowed in place of space, and it's not always clear why.
For instance, shells other than zsh complain about the newlines marked as ⚠️ below for no good reason:
[[⚠️
alpha⚠️
<⚠️
zulu⚠️
]]
In:
for⚠️
i
in⚠️
a⚠️
b
do
...
done
The second and following ⚠️ can be explained by the fact that one can do:
for word
in for in do done
do echo "$word is part of for loop constructs"
done
And to allow that unquoted do in the list of words to loop on, that list has to be separated from the do keyword with a newline or ;.
In zsh,
for
i
in
a b
Would be taken as for i in <empty-list>; a b, short for for i in <empty-list>; do a b; done.
There, to break down long lists of loop iterations without having to resort to line continuations, you can do:
for var (
val1
val2
...
) something with $var
(here short form, but you can also use do...done if you prefer).
I can't think of any reason why one couldn't do:
cmd >⚠️
file
(other than it would look silly) but all shells I tried report a syntax error.
Also note that you can't do
echo foo
&& echo bar
The shell works one line at a time and tries to interpret the code as soon as it can after it's read it and it's syntactically valid.
After reading:
echo foo &&
The shell can't execute that yet, it needs the rest of the code that would make it syntactically valid. If interactive, it issues a $PS2 prompt to ask for more.
After reading:
echo foo
it runs echo foo, and forgets about it, ready to read, parse and runs whatever you feed it (remember shells were primarily designed to be run interactively).
Then, if you feed && echo bar, it won't know what to do with it, and errors out.
That's in contrast with the and/or keywords of the fish shell. There, you can do:
echo foo
and echo bar
In fish, and is still syntax in that for instance, you can do:
cmd1
and begin
cmd2
cmd3
end
Which you couldn't if and was a regular builtin.
But the and is not syntactically connected to what's before.
Note you can't do:
cmd1
and
cmd2
Though.