69

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

74

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
  • 28
    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
  • 1
    @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
44

-- 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' '-----------------------'
3
  • what about when you need to do this with a sequence? printf '-%.0s' {1..54}
    – qodeninja
    Aug 18, 2019 at 18:42
  • 5
    @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
10

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 at 13:36
1

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.