69

I don't do terribly much shell scripting, so I was a little surprised when I was reading the documentation for git submodule and I saw the syntax they used in this documentation:

A non-zero return from the command in any submodule causes the processing to terminate. This can be overridden by adding || : to the end of the command.

I had to look up that || : was a shorthand for forcing a command to exit successfully. Anytime I've had to make a command exit successfully, I used || true. Is || : considered to be more idiomatic?

3 Answers3

63

true was not built into the Bourne shell. : always was (it was the way to enter comments before # was introduced).

That, and because it's shorter to type is probably the main reason people prefer : over true.

Note another difference in POSIX shells (for bash, only in POSIX mode): while true is a regular builtin (doesn't even have to be builtin), : is a special builtin. That has a few implications, most of which are unlikely to have any impact in this particular case:

  • If a : command fails, including because of a failed redirection, that causes the shell to exit. In practice, that probably won't make a difference unless you pass redirections to :

    $ sh -c ': > /   ; echo HERE'
    sh: 1: cannot create /: Is a directory
    $ sh -c 'true > /; echo HERE'
    sh: 1: cannot create /: Is a directory
    HERE
    
  • in var=value :, var remains set to value after : returns, not in the case of true:

    $ var=1; var=2 :   ; echo "$var"
    2
    $ var=1; var=2 true; echo "$var"
    1
    

Also note that || true works in shells of the rc and csh families but not || : (but not to cancel set -e in csh).

|| : is not the same as :. It means or run : otherwise (that is, if the preceding pipeline fails).

set -e
false

Would cause the shell to exit because of set -e (aka the errexit option) and false has a non-zero (failure) exit status. The set -e effect is cancelled if the command that returns a non-zero exit status is used as a condition like in:

if false; then ...
while false; do ...
false && : ...
false || : ...

false && : only cancels set -e. false || : cancels the effect of set -e and sets the exit status to 0 so is more idiomatic to say that we want to ignore a failure exit code of the command. Most would argue that || true is more legible (conveys the intention more clearly).

  • 7
    && : is brilliant, are there any docs or further reading on this? Google falls short on me trying to find this sort of keywords… – Ian Bytchek Oct 08 '15 at 08:11
  • @IanBytchek, check your shell's manual. See info bash set for bash or info zsh errexit for zsh or set --help 2>&1 | pager for ksh93 for instance. – Stéphane Chazelas Aug 10 '21 at 15:41
13

Most of these responses fail to address the most common use of :.

First, this discussion is not related to any shell that is not a Bourne shell (sh) derivative. That said, all Bourne derivative shells see true and : as the same thing. Programmers used to be encouraged to use : instead of true, because : is always a built-in while there used to be cases where true was not always a built-in.

: has two uses. It is not a synonym for #, but it has a different function. When debugging your script under a set -x, lines where # is used are dropped by the parser and totally ignored, whereas lines with : are parsed and evaluated. This is really useful in debugging since under -x those lines are shown and their value after evaluation are displayed. It is like putting print statements in your code that only show under -x mode. Be careful with the values after the : since they are real code and the side-effects can affect your program.

cdr
  • 149
8

Generally, in bash, the colon : and true is equivalent.

Is || : considered to be more idiomatic?

I think it is based on the context.

If you want a return value, or a condition is always true, you should use true keyword, it's will make your code more clearly and let the viewers know that you want emphasize the value true, i.e:

while true; do something

or

<commnad>
RETURN_VALUE= $? || true

And if you want to do nothing, or NOP in shell, you should use colon :

if condition
then
    : # DO NOTHING HERE
else
    do something
fi 

or

while conditon
do
    : # DO NOTHING HERE
done
cuonglm
  • 153,898