Bash portability: echo or printf

I was glancing at a bash book to see what topics they covered. The author made a comment I hadn’t seen elsewhere about echo, printf and portability. This was something new to me. I went to the IEEE standards doc for the shell and echo:

“It is not possible to use echo portably across all POSIX systems unless both -n (as the first argument) and escape sequences are omitted.”

“New applications are encouraged to use printf instead of echo.”

“The echo utility has not been made obsolescent because of its extremely widespread use in historical applications. Conforming applications that wish to do prompting without <newline> characters or that could possibly be expecting to echo a -n, should use the printf utility derived from the Ninth Edition system.”

Most scripts I see, even grepping those in /etc/init.d, use a combination of printf and echo, but mostly echo.

I was thinking about making “set -o posix” my standard. From your work experience, what are your thoughts for portability, go with printf or stay with echo and use printf if necessary.

Thank you in advance.

If you have bash, then you have the builtin echo. It’s /bin/echo that may or may not support -n.

Also if you are working with Linux systems and the scripts will only be used there, e.g. /etc/init.d, then there is no need for those scripts to be portable to non-Linux systems. If you are writing some scripts that may be used for Solaris, or BSD, then you might want to use bash or stick to portable constructs.

When you want to stick to the POSIX standard, you should not use bash in he first place, but the POSIX shell. Which is* sh*.

henk@boven:~> ls -l $(which sh)
lrwxrwxrwx 1 root root 9 jan  2 20:32 /usr/bin/sh -> /bin/bash
henk@boven:~>

shows that you should use

#!/usr/bin/sh

as shebang. Documentation is of course in

man sh

The above also shows that* /usr/bin/sh* is a symlink to /bin/bash, but be assured that this executable knows how it is called and thus interpretation differences are done. I remember a thread here on the Forums where somebody complaind that bash did not what it should do. In fact he called sh and that behaved different (as it should) on that particular syntax.

It does seem to make more sense to use /bin/sh rather than --posix/set. I’ve never quite understood everything in the “INVOCATION” section of the bash man page.

I did a
“grep ‘#!’ /etc/init.d/*|cut -d’#’ -f2|sort|uniq -c”
and OpenSUSE uses both forms. :smiley:

13 ! /bin/bash
14 !/bin/bash
64 ! /bin/sh
20 !/bin/sh

I’ll definitely be more aware of echo/printf and escape sequences/options. I know what I’ll check in the index, when I go browse script books at the local bookstore.

Thank you.

First I must improve my post. Better use* #!/bin/sh then #!/usr/bin/sh*. The PATH variable makes which to come with the second one, but the first one is more likely to work on manu Unix/Linux systems.

Those different forms are not that strange at all. Some programmers write Bash scripts, others write Posix-shell scripts and thus they use different shebangs. I do write many Korne-shell scripts and thus start those with #!/bin/ksh. The extra white space is just a matter of personal preference. Both are allowed.

You seem to think that all what you find in openSUSE is written by one very coordinated team. This is not the case. Many of those scripts have allready a long life behind them from Unix days on. And it is only naturaly that they show different styles of programming.

I think you should concentrate on what you want. When you want to write shell scripts that adhere to the Posix standard, you should use the Posix shell. consequently those scripts start with* #!/bin/sh*. And* man sh* gives you the programmers manual. Also you should try to call all tools you use in your scipts to use only POSIX compatible features (options). E.g. for the man page of ls use man 1p ls.

$ grep -h ‘^#!’ /etc/init.d/* | sed -e ‘s/! /!/’ | sort | uniq -c
3 #!/bin/bash
36 #!/bin/sh
61 #!/bin/sh -e
1 #!/usr/bin/env bash

Not SuSe, but slightly better command.