0

I have been reading "The Linux command line book" and I have encountered this line continuation character and I am confused why do we use it with this find command:

find playground \
    \( \
        -type f \
        -not -perm 0600 \
        -exec chmod 0600 {} \; \
    \) \
    -or \
    \(
        other options...
    \)

and why we didn't use it with this if statement :

if [ $x -eq 5 ]; then 
    echo "x equals 5."
else
    echo "x does not equal 5."
fi
ilkkachu
  • 138,973
Susano
  • 135

2 Answers2

5

The simple answer is that because the former needs it, and the latter doesn't.

That find command is a single simple shell command, which just takes a number of distinct arguments, and has a structure of its own. Those arguments are just not meaningful to the shell, so it doesn't know there's e.g. a logical connection between the ( and the ). The whole command could be written on a single line, it would just be harder to read.

Without the line continuations, find would run on playground with the default printing action, and then the shell would try to run the command ( without arguments (or, the command -type in a subshell, if you were to remove the escape from the (, too):

find playground
    \(
        -type f 
        ...

On the other hand, the if compound statement is part of the shell syntax, and the shell knows what parts there are to expect. After the then there must be a command, and eventually an else or fi. The whole structure could also be written on a single line, but then we'd need to add semicolons before the else and the fi. (In the same way echo foo; echo bar requires to semicolon or a newline to be taken as two commands.)

ilkkachu
  • 138,973
3

This is a particularly complex example because some of the \ there are what you're calling "line-continuation" but others are to protect characters so the shell doesn't interpret them and instead passes them to find. Specifically, the \(, \) and \; are there so that the shell doesn't interpret the escaped characters and passes them as-is to find. The rest, the \ that aren't immediately before a non-space character are line continuation signals.

In general, if you want to break a command, you need the \ unless you break on one of the "list terminator" characters. So, if you cut after one of these, you don't need the \:

; & && || | |& ;; 

For example, echo foo && echo bar can be written as:

echo foo &&
echo bar

No need for \. Alternatively, the same thing can also be written as:

echo \
foo \
&&
echo \
bar

Note how I have used the \ when cutting at places that are neither the end of a command nor a list terminator.

If you cut a command anywhere else, you need the \. You don't need the \ in the if ... then ... else ... example you show because there, you aren't cutting a command. Each command is on its own line, and that's fine. You only need the \ if you want to break a single command onto multiple lines.

As @paul_pedant correctly pointed out in the comments, you can make the command much clearer if you use single quotes to escape things for find:

find playground \
    '(' \
        -type f \
        -not -perm 0600 \
        -exec chmod 0600 {} ';' \
    ')' \
    -or \
    '('
        other options...
    ')'
terdon
  • 242,166
  • 2
    As terdon says, some of those \ are line continuations (essentially, they quote the newline), and some are plain quoting. I really dislike that confusion. It is equally valid to quote the other find options as '(' ')' ';' and to me it is more readable and thus less bug-prone. – Paul_Pedant Mar 05 '20 at 14:54
  • @Paul_Pedant very good point! I added an example using single quotes. Thanks! – terdon Mar 05 '20 at 15:10
  • @terdon I know what they are but thanks for the detailed answer it helped so much but one more thing what makes these ; & && || | |& ;; characters special about these line continuation thing Is that because of the interpreter of the shell itself or I'm getting it wrong? – Susano Mar 05 '20 at 20:33
  • 1
    @MahmoudSalah yes, that's just how the shell's grammar works. – terdon Mar 05 '20 at 20:35