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

admin2025-04-21  2

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?

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?

Share Improve this question asked Jan 22 at 20:57 RedshoeRedshoe 1897 bronze badges 9
  • 4 -- is special separator for shell commands! Try: printf -- "--" – F. Hauri - Give Up GitHub Commented Jan 22 at 20:59
  • Ahh. That works. Thank you! – Redshoe Commented Jan 22 at 21:00
  • Search for -- in man bash and man sh! – F. Hauri - Give Up GitHub Commented Jan 22 at 21:02
  • 4 printf "%s\n" -- also works. The first argument should be the format string. – Barmar Commented Jan 22 at 21:08
  • Beside the point, but those are Unicode U+2D HYPHEN-MINUS -, not U+2013 EN DASH . – wjandrea Commented Jan 22 at 21:28
 |  Show 4 more comments

2 Answers 2

Reset to default 1

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.

According to the man page for printf, there are two ways it is used:

printf FORMAT [ARGUMENT]...

printf OPTION

The options are specified using two dashes followed by the option name.

--help display this help and exit

--version output version information and exit

So when you specify printf "--", the printf command thinks you are using the command with an option.

Since the printf command allows the standard set of options, you can use the -- option to delimit (end) the option list and then use the format of "--". See the common options man page:

-- Delimit the option list. Later arguments, if any, are treated as operands even if they begin with -. For example, sort -- -r reads from the file named -r.

printf -- "--"

As a side note for others, you may need to use single quotes rather than double quotes with some format specifiers in order to prevent the shell from doing substitution on the command line before invoking printf and passing the modified command line to it.

转载请注明原文地址:http://anycun.com/QandA/1745228618a90499.html