6

man printf, info printf and printf --help are all pretty useless to me; I want an explanation of the FORMAT options. For example, I could use:

printf '%s\n' foo bar

and get output:

foo
bar

From general reading online I surmise that %s means something like 'separator', so with it printf prints every argument provided to it, separated by newlines.

I've also seen references here and there to %d and a number of others (I think it's something to do with digits?). Could someone please provide an overview of these formatting options?

2
  • as an aside, an overview of the formatting options (or conversion specifiers) would be unnecessarily verbose for an answer, in my opinion.
    – Josh McGee
    Jul 23, 2013 at 19:34
  • My basic expectation would be that it follows standard printf functionality from the c library. %s is string, %d is decimal, %f is floating point. As per the answer, it does with some extended capability.
    – BillThor
    Jul 23, 2013 at 23:39

3 Answers 3

12

For bash, the primary resource is man bash. For builtins specifically, there is the help builtin. Here is a quote from help printf.

In addition to the standard format specifications described in printf(1) and printf(3), printf interprets:

 %b        expand backslash escape sequences in the corresponding argument
 %q        quote the argument in a way that can be reused as shell input
 %(fmt)T output the date-time string resulting from using FMT as a format
       string for strftime(3)

The printf(N) notation used in the help printf means that you should refer to the manual section of the command denoted by the number in parentheses.

See man 1 printf, man 3 printf, and if you want man 3 strftime for the special %(fmt)T specifier.

You have to piece it all together yourself; the documentation does not simply list "%s is for string, %d is for digit." I believe the primary thing you are asking for is known as the conversion specification.

6

The best resource I've found is the bash-hackers.org wiki for all things related to Bash. It's what the man pages should be instead of massive pile that's tough to navigate.

There are specific topics on the builtins including printf. This page is exhaustive! It includes all the formatting options as well as examples and even a discussion section at the bottom for helping to flesh our corner cases and nuances with printf's functionality.

I've also been known to use the GNU Coreutils documentation on printf, specifically the page on the formatting options, in a pinch.

2
  • For those coming later, bash-hackers.org is gone, SEO parked. Someone has a rough backup at flokoe.github.io/bash-hackers-wiki
    – Cliff
    Nov 15 at 1:43
  • There's also the archive.org instance of the wiki, you can go back through various timeframes to see that site at various snapshots in time. Putting a link to the last one I could find before it was SEO parked - web.archive.org/web/20221128004844/https://….
    – slm
    Nov 19 at 4:17
1

First, it's important to differentiate between the following three printf varieties:

  • printf as a Bash builtin.
  • printf as an (Bash-)external executable, e.g. coreutil's /usr/bin/printf (see which printf and man 1 printf).
  • printf(..) from the C standard libary (libc) (in my case its the GNU Project glibc implementation, see man 3 printf

The first step is to find out whether the builtin or the external executable version is used when executing the command printf '%s\n' foo bar. This can be found out using the type Bash builtin on the particular shell prompt in use:

$ type printf
printf is a shell builtin

The Bash builtin printf is documented in Bash Reference Manual - 4.2 Bash Builtin Commands: printf.

While the Bash documentation doesn't have any explanation on %s or %d, it contains the following relevant information:

In addition to the standard printf(1) formats, printf interprets the following extensions: [...]

On my system (Debian 11 bullseye) man 1 printf shows that the printf executable comes from GNU coreutils.

To run the command with that executable (instead of with the builtin), use any of these statements:

env printf '%s\n' foo bar

/usr/bin/printf '%s\n' foo bar
# full path to the printf *executable* found out via command 'which printf'

The coreutils executable printf is documented in GNU Coreutils - 15.2 printf: Format and print data.

The coreutils documentation contains the following relevant information:

printf prints the format string, interpreting ‘%’ directives and ‘\’ escapes to format numeric and string arguments in a way that is mostly similar to the C ‘printf’ function. See printf format directives in The GNU C Library Reference Manual, for details. The differences are listed below. [...]

The coreutils documentation already provides additional explanations about %s and %d.

The referenced GNU C Library Reference Manual has the following sections relevant to printf(..):

And finally: The GNU C Library is (also) an implementation of the the C POSIX library standard, more or less conforming to the specifications given therein.

POSIX is formally known (in its latest version) as POSIX.1-2017, and IEEE Std 1003.1-2017, and The Open Group Technical Standard Base Specifications, Issue 7. The specification provides the "official" rules on how printf(..) is supposed to work "according to specification".

  • POSIX.1-2017 Specification Home
    • POSIX.1-2017 - Volume 'System Interfaces'
      • POSIX.1-2017 - dprintf, fprintf, printf, snprintf, sprintf - print formatted output

        [...] The functionality described on this reference page is aligned with the ISO C standard. Any conflict between the requirements described here and the ISO C standard is unintentional. This volume of POSIX.1-2017 defers to the ISO C standard. [...]
        [...] The printf() function shall place output on the standard output stream stdout.
        [...] Each of these functions converts, formats, and prints its arguments under control of the format. The format is a character string, beginning and ending in its initial shift state, if any. The format is composed of zero or more directives: ordinary characters, which are simply copied to the output stream, and conversion specifications, each of which shall result in the fetching of zero or more arguments. The results are undefined if there are insufficient arguments for the format. If the format is exhausted while arguments remain, the excess arguments shall be evaluated but are otherwise ignored. [...]
        [...] In format strings containing the % form of conversion specification, each conversion specification uses the first unused argument in the argument list. [...]
        [...] Each conversion specification is introduced by the '%' character [...], after which the following appear in sequence: [...] A conversion specifier character that indicates the type of conversion to be applied. [...]
        The conversion specifiers and their meanings are:
        d,i: The int argument shall be converted to a signed decimal in the style "[-]dddd". The precision specifies the minimum number of digits to appear; if the value being converted can be represented in fewer digits, it shall be expanded with leading zeros. The default precision is 1. The result of converting zero with an explicit precision of zero shall be no characters.
        [...]
        s: The argument shall be a pointer to an array of char. Bytes from the array shall be written up to (but not including) any terminating null byte. If the precision is specified, no more than that many bytes shall be written. If the precision is not specified or is greater than the size of the array, the application shall ensure that the array contains a null byte.
        [...]

So apparently, to fully drill down to the definitions, the next step would be to look at the appropriate "ISO C Standard" (also known as "ANSI C") revision, formally specified in ISO/IEC 9899, e.g. in revision ISO/IEC 9899:2018, also known as C17. Finding the official, full specification for ISO C Standard revisions is not that easy, as this StackOverflow question shows.

But suffice to say, to find out the intended meaning and the actual behavior of "Bash's builtin printf formatting options" for the more exotic varieties may require to drill down through several layers of implementations, abstractions, and specifications.

Also important

Keep in mind that different releases of these softwares may have varying available options and may change semantics of existing options. It's a best practice to refer to the manual version matching to the version in use. E.g. The GNU C Library Reference Manual provides versioned manual releases.

You must log in to answer this question.

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