73

I'm trying to use printf to format some pretty output in a bash script

e.g.:

-----------------------  
| This is some output | 
-----------------------

But I've stumbled over some behavior I don't understand.

$ printf "--"

gives me the error:

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

and

$ printf "-stuff"

results in

-bash: printf: -s: invalid option

So apparently printf thinks I'm trying to pass some arguments while I'm not.

Meanwhile, completely by accident, I've found this workaround:

$ printf -- "--- this works now ----\n"

gives me

--- this works now ----

Can anyone explain this behavior?

2
  • 1
    See also unix.stackexchange.com/questions/11376/…
    – manatwork
    Oct 17, 2011 at 11:51
  • Out of intereset, are there any implementations of echo that would fail when doing echo ------------? Most only support -n (no trailing newline), -e (interpret backslash-escaped chars) and possible -E (do NOT interpret them) and do not error out when other option-like arguments are encountered, right? (EDIT: GNU's /bin/echo also supports --help and --version.)
    – janmoesen
    Oct 18, 2011 at 6:34

4 Answers 4

79

The -- is used to tell the program that whatever follows should not be interpreted as a command line option to printf.

Thus the printf "--" you tried basically ended up as "printf with no arguments" and therefore failed.

10
  • 33
    In other words, to print -- you can run printf -- --.
    – l0b0
    Oct 17, 2011 at 12:14
  • 2
    ... and printf -- is the same as printf (you get the same message)
    – Peter.O
    Oct 17, 2011 at 14:54
  • 4
    Note that printf -- $fmt is not portable. On busybox 1.30.1, printf -- '%s\n' hello yields --. See also: pubs.opengroup.org/onlinepubs/009695399/utilities/printf.html
    – kelvin
    Nov 17, 2019 at 22:18
  • @kelvin, What? busybox/printf.c#L421 Apr 26, 2020 at 0:11
  • 2
    @AlexanderShukaev My bad, I tested it on LineageOS and now I see that it uses mksh in adb shell instead of busybox. It works normally with busybox printf -- '%s\n' hello. The point about portability still stands though.
    – kelvin
    Apr 26, 2020 at 3:53
45

-- is being interpreted as an option (in this case, to signify that there are no more options).

A format string should always be included when using printf to prevent bad interpretation. For your particular case:

printf '%s\n' '-----------------------'
6
  • 1
    what about when you need to do this with a sequence? printf '-%.0s' {1..54}
    – qodeninja
    Aug 18, 2019 at 18:42
  • 7
    @qodeninja Then you actually do want to use -- :-) printf -- '-%.0s' {1..54}
    – Chris Down
    Aug 19, 2019 at 14:33
  • @qodeninja printf '\055%.s' {1..54}
    – jhnc
    Jul 14, 2021 at 16:14
  • how portable is this?
    – CervEd
    Oct 10, 2023 at 7:19
  • @CervEd This is POSIX, it's highly portable. Certainly more so than printf --, which doesn't work in (for example) mksh.
    – Chris Down
    Oct 10, 2023 at 7:21
12

There are differences between printf builtin and /usr/bin/printf, the second one do "what you mean" without these annoying errors.

printf "-----"             # error
printf -- "-----"          # ok
/usr/bin/printf "-----"    # ok
/usr/bin/printf -- "-----" # ok
1
  • FYI /usr/bin/printf '--' gives /usr/bin/printf: missing operand error.
    – midnite
    Apr 19, 2022 at 13:36
3

POSIX provides the option of using octal encoding.

 printf "--"

can become:

printf "\055-"

This is a portable way to avoid the ambiguity of whether -- is being used as a format string or as a marker for the end of options.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .