27

I was looking through an entrypoint script for a docker image and they had the following lines (53-54)

: ${POSTGRES_USER:=postgres}
: ${POSTGRES_DB:=$POSTGRES_USER}

I saw this thread What is the purpose of the : (colon) GNU Bash builtin?

and was able to figure out : meant true and that the := was used to assign default values, but it doesn't really touch upon what does : at the beginning of the line at least for this specific case.

Community
  • 1
  • 1
m0meni
  • 16,006
  • 16
  • 82
  • 141

1 Answers1

72

In the Bourne shell and derivatives like Bash, : is a no-op command: that is, it doesn't do anything, but arguments are evaluated normally. Contrast this with a comment (#), which does nothing at all (everthing following the # is simply ignored).

This syntax:

: ${POSTGRES_USER:=postgres}

Is commonly used to assign default values to variables. The syntax ${POSTGRES_USER:=postgres} (a) will set the variable POSTGRES_USER to postgres only if it does not already have a value, and will then (b) evaluate to the value of $POSTGRES_USER. If we used a comment:

# ${POSTGRES_USER:=postgres}

...nothing at all would happen, because the shell simply ignores the entire line. Using : means that the ${...} expression is still evaluated, so POSTGRES_USER is assigned a value if necessary.

Update

If there was no : at the beginning of the line, then this:

${POSTGRES_USER:=postgres}

would be a shell command! The shell would first evaluate the variable expansion and come up with something like postgres, so you would have a shell script that effectively looked like this:

postgres

Which would probably give you the error:

bash: postgres: command not found...
larsks
  • 277,717
  • 41
  • 399
  • 399
  • Oh yeah I've seen that before when forgetting to put echo before an env variable. Okay that makes a lot of sense. – m0meni Sep 02 '15 at 00:57
  • 6
    It might worth noting that we **can't** use `:=` outside the `${}`, such as `POSTGRES_USER:=postgres`, as `:=` is part of the shell parameter expansion https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#Shell-Parameter-Expansion – hashlash Jun 13 '20 at 07:58
  • 5
    Great answer. Seems to me the syntax `POSTGRES_USER=${POSTGRES_USER:-postgres}` has a lot clearer intent, is it not equivalent in "99% of cases"?? – Oliver Nov 02 '20 at 22:05
  • Strange, my groovy command in a pipe runs a lot more slowly when I use `:` instead of `#` (though I don't see output). – Sridhar Sarnobat Jun 11 '21 at 05:10