26

What do the '&&', '\' and '-' mean at the end of bash commands?

In particular, I came across the following combination of lines that are supposed to add public keys to Ubuntu's aptitude package manager, what are those characters used here for?

    gpg --keyserver keyserver.ubuntu.com --recv 26C2E075 && \
    gpg --export --armor 26C2E075 | sudo apt-key add - && \
    sudo apt-get update
Kyle Brandt
  • 83,619
  • 74
  • 305
  • 448
Alex
  • 2,357
  • 5
  • 32
  • 41

4 Answers4

51

"&&" is used to chain commands together, such that the next command is run if and only if the preceding command exited without errors (or, more accurately, exits with a return code of 0).

"\" by itself at the end of a line is a means of concatenating lines together. So the following two lines:

gpg --keyserver keyserver.ubuntu.com --recv 26C2E075 && \
gpg --export --armor 26C2E075

are processed exactly the same as if the line was written as the single line:

gpg --keyserver keyserver.ubuntu.com --recv 26C2E075 && gpg --export --armor 26C2E075

"-" is a command line argument with no specific bash function. Exactly how it is handled is dependent on the command being run (in this case apt-key). Depending on context, it's typically used to indicate either "read data from stdin rather than from a file", or "process the remainder of the line as data rather than as command line arguments".

goldPseudo
  • 1,106
  • 1
  • 9
  • 15
  • 6
    In this case, '-' is not a parameter of sudo but of 'apt-key', meaning that instead of a key file, 'apt-key' is using the data coming through the pipe ('|') to its stdin as a key. The "gpg --export" option, without having '--output a_file_name.key', push a new key out of the gpg stdout, through the pipe ('|') to the stdin of 'apt-key' Easy :-) – edomaur Aug 13 '09 at 07:39
  • 2
    whoops. that's what i get for answering questions while half asleep. fixed. – goldPseudo Aug 13 '09 at 15:00
12
&& == if the first command succeeded, run the next one
\ == the next line is part of the first line, not two seperate lines
- == read the input from stdin (console)
rodjek
  • 3,327
  • 17
  • 14
6

&& Is the logical AND:
&& is a way of expressing Logical AND, meaning the entire expression is True only if both sides of it are true. In logic, it is said the the entire statement (P&Q) is only true when both P and Q are true.

As a consequence of this, computers generally treat P&Q as a short-circuit evaluation. So since the entire statement will only be True if Both P and Q are true, then if P is false, the statement Q is not evaluated. Basically computers are lazy (efficient), and don't bother evaluating Q if they don't have too. This is also True of logical OR, see the previous link.

The Three Contexts of && in Bash:

1) Using Short-Circuit Evaluation with the exit status of a Command:
Every command has an exit status. If a command has an error the it has an exit status that is non-zero. So if the exit status is non-zero and && is used to chain commands together into a statement, later commands won't be evaluated (executed) if the earlier one did not have an exit status of 0 (True). This is because of short-circuit evaluation. So if you have:

P && Q

Q will not be executed if P was not true ( if P exits with a status of anything but 0, it is not true). Just the same as:

./configure && make

make will not be executed if configure had an error, wasn't true. So basically, then ends up being a way of writing in if then statement:

if ./configure ; then
   make
fi

Keep in mind then in most contexts 0 is false, but not when it comes to an exit status.

2) && Can be Used in Bash's built in [[ ]] test command:

&& Can also be used inside of the built-in test command in bash [[ ]] to combine expressions in a similar fashion as combining commands. The entire test operation will only be true if both operands (sides) of && are true, for example:

if [[ ( $a -gt 2 ) && ( $a -lt 5 ) ]]; then ... 

would be a way of saying if $a is an integer between 2 and 5 (not including 2 and 5).

3) Arithmetic Evaluation:

Lastly, && can be used in arithmetic evaluation as Logical AND. If both (logical AND) of the numbers in the following are non-zero, it returns 0, else 1 is returned:

kbrandt@desktop:~/$ echo $((1 & 1))
1
kbrandt@desktop:~/$ echo $((0 && 1))
0
Kyle Brandt
  • 83,619
  • 74
  • 305
  • 448
  • @Kyle: && used outside a logical expression is the "AND control operator", similar behavior but technically different – drAlberT Aug 13 '09 at 12:23
  • Don't follow your comment, what do you mean outside a logical expression? – Kyle Brandt Aug 13 '09 at 12:31
  • I mean that in an expression the && control operator assumes the mean of "logical and", otherwise it is only an "and". It is the "AND control operator", used in lists. logical operators are used in the context of arithmetic expansion, within expressions. – drAlberT Aug 13 '09 at 15:52
  • in the `if [./configure]` example, you should remove the brackets. The correct is `if ./configure; then make...` – Juliano Aug 13 '09 at 16:14
  • Juliano, Good catch, will update. AlberT, is there any difference other than the terms the man pages give it? – Kyle Brandt Aug 13 '09 at 16:59
  • Kyle, they are technically different meanings. The names used by the man in different contexts are meaningful in fact when the same typographical "&&" appears into an arithmetical expression it behaves as a "logical and operator", when it appears between two commands instead it is a "control operator", meaning it really controls the execution flow of the statements. The difference is subtile but meaningful – drAlberT Aug 13 '09 at 17:12
4

I think you will better with an explanation of the "real" meaning, implications are another thing :)

  • && is the "AND" control operator. From bash man:
    The control operators && and || denote AND lists and OR lists, respectively.
    An AND list has the form  
        command1 && command2     
    command2 is executed if, and only if, command1 returns an exit status of zero.
    [..cut..]
    The return status of AND and OR lists is the exit status of the last command
    executed in the list.
    
    A control operator is
    A token that performs a control function.  It is one of the following symbols:
        || & && ; ;; ( ) | 
    
  • \ is the "escape character", and it is one of the three quoting mechanisms available in bash:
    QUOTING
       Quoting is used to remove the special meaning of certain characters or words to the shell.
    [..cut..]
       There are three quoting mechanisms: the escape character, single quotes, and double quotes.
       A  non-quoted  backslash (\) is the escape character.  It preserves the literal value of the next character that follows, with the exception of .  If a \ pair appears, and the backslash is not itself quoted, the \ is treated as a line continuation (that is, it is removed from the input stream and effectively ignored).
    [..cut..]
    The backslash retains its special meaning only when followed by one of the following characters: $, `, ", \, or .
    
    This means that if you put an escape character (the "\") at the very end of a line you are in fact escaping the new line char that immediately follows it (the RETURN char) thus having the effect of "continue the line" others have already explained in their answer
  • The dash char "-" that some commands accept as parameter is a convention, not a shell special char or operator. As other already pointed out, it is a sort of place-marker for the standard I/O streams. Depending on the program we refers to it may stay for stdin (the standard input) or stdout (the standard output).

My 2 cents

drAlberT
  • 10,949
  • 7
  • 39
  • 52
  • 1
    Probably going to be a case of tl;dr. Pasting giant chunks of a manpage - enlightening as it is - will probably just intimidate the OP. – rodjek Aug 13 '09 at 12:33