Files
hpr-knowledge-base/hpr_transcripts/hpr4667.txt
T

199 lines
13 KiB
Plaintext
Raw Normal View History

Episode: 4667
Title: UNIX Curio #9 - printf
Source: https://hub.hackerpublicradio.org/ccdn.php?filename=/eps/hpr4667/hpr4667.mp3
Transcribed: 2026-07-31 16:16:16 (official HPR transcript)
---
This is Hacker Public Radio Episode 4667, for 2026-06-23
Today's show is entitled, "UNIX Curio #9 - printf"
The host is Vance and the duration is 00:20:39
The flag is Clean, and the license is CC-BY-SA
The summary is "Displaying text without the echo"
Hi there, I'm Phance and welcome to Unix Curio number nine.
This series is dedicated to exploring little known and occasionally useful, trinkets lurking
in the dusty corners of Unix-like operating systems.
Instead of having an echo, why don't we talk about the echo utility a little bit?
The echo command is very useful.
It prints the arguments given to it, followed by a new line character.
The new line is sometimes also called a line feed character, depending on who is writing
or speaking, and it has the ASCII decimal value 10.
Also has many uses either in a script or interactively on the command line.
This utility can be used to display text, the value of variable, or the result of a path
name expansion.
It can also feed text to another command in a pipeline.
As useful as echo is, it should come as no surprise that it first appeared early on
in Bell Laboratories' second edition Unix in 1972.
This initial version accepted no options.
Although the manual page doesn't explicitly say output is followed by a new line character,
the description of writing as a line seems to imply it.
In seventh edition Unix, the manual page makes that clear and also features the addition
of the hyphen and option that's November in the phonetic alphabet, which causes echo
to print the arguments without a trailing new line character.
Eight edition Unix's echo gained the hyphen E option.
Coincidentally, that's echo in the phonetic alphabet, which allows the use of certain
escape codes from the C programming language to be used.
These variations cause differences in behavior between different versions of echo.
We'll running echo, hyphen N, something on your system, output the text, something without
a new line, or the text, hyphen N something followed by a new line.
These get even trickier when the command arguments include parameter or pass name expansions.
If there are files named hyphen N and something in the current directory, what does echo
asterisk output?
Like the previous question, that depends on whether or not your version of echo treats hyphen
N as an option.
You can't get around this ambiguity by quoting or escaping the asterisk because that
just causes echo to print a literal asterisk.
The solution was to create a new utility, which is the first Unix Curio for today, print
F.
This command allows a user to print text similar to the way the identically named function
works in the C programming language.
You run print F followed by a format string followed by zero or more arguments.
No new line characters are printed unless specifically indicated by the format string or
the arguments.
To use print F to print the word something without a new line, that would just be print
F something.
This demonstrates that you don't need any arguments.
In this example, the format string is just a set of regular characters to be displayed.
If you wanted a new line character at the end, print F double quote something backslash
n double quote would give you that.
In this case, the format string needs to be quoted so the backslash n isn't interpreted
by the shell.
In addition to backslash n for a new line, you can also use backslash a for an alert, which
rings the terminal bell, backslash b for a backspace, backslash f for a form feed, backslash
r for a carriage return, backslash t for a horizontal tab, backslash v for a vertical tab,
and backslash backslash to get a literal backslash.
In addition to these special characters, any arbitrary bite can be included using a backslash
followed by one to three octal digits.
However, it might be difficult to predict what will be output because it can differ
based on the character set the terminal is using.
It is safer and more portable to stick to the predefined characters if possible.
The real magic of the print F utility comes from using conversion specifications in the
format string.
Probably the simplest of these to explain is the percent sign S conversion specification.
It represents a string of any length.
The command print F double-quote high percent sign S, how are you backslash n double-quote followed
by a list of names as arguments would print the greeting on a separate line for each name,
putting it in the place occupied by the percent sign S.
The format string is reused as many times as needed to consume all of the arguments.
Take for example the command print F double-quote high percent sign S, have you met percent
sign S, backslash n double-quote?
If this is run with two name arguments, it would print the sentence on one line using both
names.
If run with four name arguments, it would print the sentence twice once with the first two names
and again with the second two names.
If you only gave it three names, the last percent sign S conversion specification would
be replaced with a null string.
Three other items can also be given in each conversion specification.
Flags the field width and the precision.
The exact meanings of these depend on which type of conversion specifier character you
are using.
For percent sign S, using a hyphen as the flag causes the text to be left justified instead
of the default right justified.
A field width causes the printed field to be at least as long as the number given and
a precision limits the number of bytes written from the string to the number given.
Some examples to illustrate these are included in these shown notes.
While percent sign S is probably the most commonly used conversion specification, others
are available.
A whole set of them are dedicated to printing integer values as a sign decimal and unsigned
decimal and unsigned octal or an unsigned hexadecimal number.
These can also take flags a field width and a precision.
I think the details and nuances of all this are two complex to clearly explain here, so
I will just refer you to the POSIX file format notation specification linked in the
shown notes.
Be aware that unlike the printf function in the C programming language, the printf utility
is not obligated to accept conversion specifications for floating point numbers.
While some implementations might support this, scripts intended to be portable, should
limit themselves to the restricted set required by the POSIX standard.
To more conversion specifications are worth mentioning, the first is only required by the standard
for the printf utility, not the C function and is percent sign B.
This is the same as percent sign S, except that certain backslash escape sequences in the
arguments will be treated specially.
This includes all the ones described above, except for the one using octal digits to represent
a byte.
In an argument, this is instead represented by backslash 0 followed by one to three octal digits.
An additional backslash escape sequence accepted is backslash C.
This does not print anything itself, but causes printf to immediately halt output.
The final conversion specification is percent sign percent sign, which just outputs a literal
percent sign.
You can't use a bare percent sign in the format string because printf expects that to introduce
a conversion specification.
Be careful not to get tripped up by this when trying to print some value as a percentage.
Let's go back to the situation I was describing with echo.
We have files named hyphen n and something in the current directory and want to print all
their names separated by spaces.
We could do that with printf double quote, percent sign S, space double quote, space
asterisk, which would not treat the hyphen n as an option.
However, the output might look a little weird because there wouldn't be a new line character
at the end.
We could insert that new line by using percent sign B instead of percent sign S and following
the asterisk with a second argument, backslash n backslash C as noted before that would
have to be quoted to prevent the shell from interpreting the backslashes.
The backslash C is there to prevent the final space in the format string from being printed
after the new line.
Using the percent sign B conversion specification can therefore solve one problem but it also
introduces another.
Since which include a backslash can be interpreted as escape sequences and many systems
are fine with allowing backslashes in file names.
I've included an example of this in the show notes.
In cases where you're just using the printf utility to display text, it's usually not a big
deal if the output looks a little wonky.
Where you really need to be careful is when the text is being piped to another program
as control characters and other oddities might cause unexpected results.
And can potentially even create security problems if processed by a script or utility running
as a privileged user.
The printf utility looks to have shown up first in 1986's 9th edition Unix, though
the earliest manual page I could find is from the 10th edition.
Its first appearance in BSD seems to be from 1990 in the 4.3 Reno release.
Two years later it was added to issue 4 of the open groups CIE specification.
From what I can tell the printf utility did not seem to be in AT&T's system 3.
Presumably it did make it into system 5 at some point but I found it difficult to track
this down.
While echo is still suitable for use where you know for certain that you want a new line
character printed at the end and none of the arguments will start with a hyphen, consider
using the printf utility instead for displaying text.
It offers more flexibility and features than you are guaranteed to get with echo, although
it does require a bit of forethought in constructing a proper format string and arguments.
That is not necessarily a bad thing because a script's author should be thinking about what
might happen if it is called with quote strange unquote text or file names.
This episode also provides a good case for being careful when naming files.
Many file systems will allow you to use hyphens, control characters, quotation marks and
potentially any character other than a slash or a null byte in a file name.
As we've seen some of these characters can create problems for standard utilities.
While it can feel limiting, especially for people not using English, the safest file
names to use on a unix-like system consists only of characters in the portable file name
character set as defined by posics and where the first character is not a hyphen.
This set includes the lower case and upper case letters a through Z or Z as some people pronounce
it.
The numerals 0 through 9 and the period underscore and hyphen, notably it does not include
the space character.
That leads me to another unix-curio that I only just now discovered while researching
this episode.
This is the path check utility spelled PA THCHK or in the phonetic alphabet Papa Alpha
Tango Hotel Charlie Hotel Kilo.
It can be run with one or more strings as arguments, checks each one against a set of rules
for path names and outputs an error message for each problem found.
By default, it checks against the following limits on the system where it's being run.
There are some number of bytes in the full path, maximum number of bytes in any component
of the path, all byte sequences must be valid in the given directory and the user running
the program must have access to all directories referenced.
If run with the hyphen lower case P option, that's Papa in the phonetic alphabet, instead
of those limits, it checks against POSIX limits, a maximum of 256 bytes in the full path,
a maximum of 14 bytes in each component of the path, and each component must only include
characters from the portable set.
The hyphen uppercase P option adds warnings if any component starts with a hyphen or if
the path name is completely empty.
While the exit status will tell you if the check succeeded or not, I don't feel like the
path check utility is well suited to be used in an automated fashion.
As the exact wording of its output is not specified, and checks cannot be selected individually.
However, it can be used interactively to validate path names you aren't sure about.
See the linked specification in these show notes for full details.
Thanks for listening, and keep an eye out for the next Unix Curio, which will be about
check sums here on hacker public radio.
If you have a question or a suggestion for a future topic, please comment on this episode
on the HPR website.
You have been listening to the Hacker Public Radio podcast, at hackerpublicradio.org.
Today's show was contributed by a HPR listener like yourself.
If you ever thought of recording a podcast, then visit the HPR site to find out how easy it really is.
Hosting for HPR has been kindly provided by anhonesthost.com, the Internet Archive, rsync.net, and the HPR Community Content Delivery Network.
Unless otherwise stated, today's show is released under a Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.