9

I am updating an old script and came across a pattern I am unfamiliar with:

# NOTE The | : always returns true so the <cmd> doesn't fail
<cmd> | :

I've only ever seen this pattern used in a fork bomb example. If someone were to ask me how to accomplish what is stated in the comment, I would have suggested:

<cmd> ||:

Before I chalk this up to a typo, has anyone seen this pattern and able to explain its use-case?

Daniel Widdis
  • 8,424
  • 13
  • 41
  • 63
aka
  • 93
  • 4

2 Answers2

8

It's a typo that also happens to have a similar effect. Differences:

  • cmd | : pipes cmd's stdout to :. Since : exits immediately, if cmd writes anything it will likely be hit with a SIGPIPE signal or EPIPE error, typically killing it.
  • cmd | : runs cmd in a subshell, nullifying environmental changes like var=value or cd /dir. Compare cd /tmp || : to cd /tmp | :.
  • cmd | : won't work if set -o pipefail is enabled.

Based on the comment it should be || :.

Technically, it's a race condition. cmd could write something before : exits, though it's unlikely. Or even more unlikely, if cmd wrote a lot it and filled up the pipe's buffer it would actually block until : exits, at which point its pending write() syscall would receive an EPIPE/SIGPIPE. You can simulate this with strace -e write yes | { sleep 0.1; :; }

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
-1

I think it's a way to suppress the standard output of the command, it would the equivalent to:

<cmd> > /dev/null

I see it usefull in scripts where you don't want to show the output of cmd

Gustavo Topete
  • 1,246
  • 1
  • 9
  • 15
  • Not equivalent. `| :` will cause failure when the program on the left-hand side tries to write to its stdout after the copy of `:`/`true` has already exited, whereas `> /dev/null` will work for any arbitrary amount of content. – Charles Duffy Mar 09 '18 at 19:59
  • @CharlesDuffy so, in a few words, if the output of cmd is too big it will produce an error? – Gustavo Topete Mar 09 '18 at 20:19