Search code examples
bash

Why can't bash printf function print '--' characters?


I can't print -- (two endashes) characters using bash printf function. When I execute the following code

printf "--"

I get the error message saying

printf: usage: printf [-v var] format [arguments]

Why is this happening? And how can I print them?


Solution

  • Solution

    Use printf -- "--" (or printf -- --; the quotes are not needed in this case).

    Why This Works

    printf is a built-in command in bash, so a plain printf executes the built-in command rather than the system /usr/bin/printf. The bash man page (for GNU bash 3.2.57 on macOS 15.2) says “Unless otherwise noted, each builtin command documented in this section as accepting options preceded by - accepts -- to signify the end of the options.” Since printf accepts an option starting with - (it accepts a -v option), it accepts -- to signify the end of the options.

    Thus the first -- in printf -- "--" tells printf to stop interpreting arguments as possible options, so the next argument must be the format string.

    Why This Is Needed

    The bash man page says the syntax for printf is:

    printf [-v var] format [arguments]

    where […] denotes something optional. If this were the true syntax for printf, then clearly the -- in printf -- must be the format, because it is not the -v. So the above is not the actual syntax for printf. It is modified by the earlier text that says commands accept -- to signify the end of options.

    Similarly, printf -x would take -x as the format string, but instead it yields an error, “-x: invalid option”. In this case, I do not see any text in the bash man page that says this can happen. (This is a deficiency in the bash documentation; it fails to specify the actual behavior of the printf command, and likely others.)

    What is happening here is that - is a ubiquitous character for introducing “switches”1 in Unix commands (whether standalone or built into a shell). So, while it is not documented, the true syntax of many commands is that arguments beginning with a - are interpreted as a user attempt to specify a switch. Then, if the switch is not recognized by the command, an error is issued. However, if we execute printf -- -x, then -- says not to consider following arguments as possible options, so -x is taken as the format string, and “-x” is printed.

    Footnote

    1 Switches are arguments that specify settings or introduce supplementary information to a command, rather than being the main things the command operates on.