All about printf

In my last article, "Fancy
Tricks for Changing Numberic Base", I explored the surprising ability of the Linux shell to convert
numeric bases on the fly, including this sweet little snippet that converts
FF hexadecimal into decimal notation:

$ echo $(( 0xFF ))
255

And, I discussed how you even could use the handy
printf command within scripts too,
such as this command to display decimal numbers in octal and hexadecimal:

$ printf "octal: %o\nhex: %x\n" 42 42
octal: 52
hex: 2a

It's pretty neat stuff, but to be honest, I rarely find myself needing
to convert numeric bases nowadays, so it's really something I file
under "funky shell tricks". Your experience may be different, so
it's still well worth learning anyway.

In this article, I thought it would be interesting to take a closer look at the
printf command, because it is so darn powerful, but
before going there, here's a
quickie: some neat ways you can make your if-then statements be more
succinct.

If/Then Statements

If you're like me, then you find yourself frequently writing
conditional statement blocks in your shell scripts. Um, I mean:

if [ you're like me ] ; then
you find yourself...

Well, you get the idea. In fact, conditional expressions are where
sequences of code turn into more sophisticated programs, whether
they're a half-dozen lines long or hundreds of lines.

This is clear and readable, but it sure takes up a lot of vertical space in
a shell script.

Fortunately, there are some ways you can tighten up things by using the
&&
and || notations in your shell scripts.

The && notation means if what's invoked prior to the && ends with a
success return code, do what's subsequent—for example:

test $(date +%w) -eq 0 && echo "Sunday"

If it's Monday afternoon when I run this code, I'll get no output,
and the echo statement isn't even evaluated. But if it's Sunday,
the above command will output appropriately.

The || notation offers the same basic functionality but with the opposite
logic: if the return code of the command prior to the || returns a fail
(non-zero) return code, then the subsequent command will be invoked:

test $(date +%w) -eq 0 || echo "It's not Sunday yet"

You also can make this even more succinct by using the [] notational
shortcut for a test—just remember to include the closing ] to ensure
it's all well formed:

[ $(date +%w -eq 0 ] || echo "it's not Sunday yet"

The biggest limitation with this notation is that there's really no
reliable and properly interpreted way to add an else clause.

You can try something like this:

cmd1 && cmd2 || cmd3

But because of precedence interpretation, it's likely to have cmd3
invoked if either cmd1 or cmd2 have a non-zero return code, which makes it
functionality different from this:

Dave Taylor has been hacking shell scripts for over thirty years. Really.
He's the author of the popular "Wicked Cool Shell Scripts" and
can be found on Twitter as @DaveTaylor and more generally at
www.DaveTaylorOnline.com.