Back: Environment
Forward: Writing New Macros for Autoconf
 
FastBack: Writing Portable Bourne Shell
Up: Writing Portable Bourne Shell
FastForward: Writing New Macros for Autoconf
Top: Autoconf, Automake, and Libtool
Contents: Table of Contents
Index: Index
About: About this document

22.4 Utilities

The utility programs commonly executed by shell scripts can have a huge impact on the portability of shell scripts, and it is important to know which utilities are universally available, and any differences certain implementations of these utilities may exhibit. According to the GNU standards document, you can rely on having access to these utilities from your scripts:

 
cat cmp cp diff echo egrep expr false grep install-info
ln ls mkdir mv pwd rm rmdir sed sleep sort tar test touch true

Here are some things that you must be aware of when using some of the tools listed above:

cat
Host architectures supply cat implementations with conflicting interpretations of, or entirely missing, the various command line options. You should avoid using any command line options to this command.

cp and mv
Unconditionally duplicated or otherwise open file descriptors can not be deleted on many operating systems, and worse on Windows the destination files cannot even be moved. Constructs like this must be avoided, for example.

 
exec > foo
mv foo bar

echo
The echo command has at least two flavors: the one takes a `-n' option to suppress the automatic newline at the end of the echoed string; the other uses an embedded `\c' notation as the last character in the echoed string for the same purpose.

If you need to emit a string without a trailing newline character, you can use the following script fragment to discover which flavor of echo you are using:

 
case echo "testing\c"`,`echo -n testing` in
  *c*,-n*) echo_n=   echo_c='(53)
' ;;
  *c*,*)   echo_n=-n echo_c= ;;
  *)       echo_n=   echo_c='\c ;;
esac

Any echo command after the shell fragment above, which shouldn't move the cursor to a new line, can now be written like so:

 
echo $echo_n "prompt:$echo_c"

In addition, you should try to avoid backslashes in echo arguments unless they are expanded by the shell. Some implementations interpret them and effectively perform another backslash expansion pass, where equally many implementations do not. This can become a really hairy problem if you need to have an echo command which doesn't perform backslash expansion, and in fact the first 150 lines of the ltconfig script distributed with Libtool are devoted to finding such a command.

ln
Not all systems support soft links. You should use the Autoconf macro `AC_PROG_LN_S' to discover what the target architecture supports, and assign the result of that test to a variable. Whenever you subsequently need to create a link you can use the command stored in the variable to do so.

 
LN_S=@LN_S@
...
$LN_S $top_srcdir/foo $dist_dir/foo

Also, you cannot rely on support for the `-f' option from all implementations of ln. Use rm before calling ln instead.

mkdir
Unfortunately, `mkdir -p' is not as portable as we might like. You must either create each directory in the path in turn, or use the mkinstalldirs script supplied by Automake.

sed
When you resort to using sed (rather, use case or expr if you can), there is no need to introduce command line scripts using the `-e' option. Even when you want to supply more than one script, you can use `;' as a command separator. The following two lines are equivalent, though the latter is cleaner:

 
$ sed -e 's/foo/bar/g -e '12q' < infile > outfile
$ sed 's/foo/bar/g;12q' < infile > outfile

Some portability zealots still go to great lengths to avoid here documents of more than twelve lines. The twelve line limit is actually a limitation in some implementations of sed, which has gradually seeped into the portable shell folklore as a general limit in all here documents. Autoconf, however, includes many here documents with far more than twelve lines, and has not generated any complaints from users. This is testament to the fact that at worst the limit is only encountered in very obscure cases -- and most likely that it is not a real limit after all.

Also, be aware that branch labels of more than eight characters are not portable to some imPlementations of sed.

Here documents are a way of redirecting literal strings into the standard input of a command. You have certainly seen them before if you have looked at other peoples shell scripts, though you may not have realised what they were called:

 
cat >> /tmp/file$$ << _EOF_
This is the text of a "here document"
_EOF_

Something else to be aware of is that the temporary files created by your scripts can become a security problem if they are left in `/tmp' or if the names are predictable. A simple way around this is to create a directory in `/tmp' that is unique to the process and owned by the process user. Some machines have a utility program for just this purpose -- mktemp -d -- or else you can always fall back to umask 077 && mkdir /tmp/$$. Having created this directory, all of the temporary files for this process should be written to that directory, and its contents removed as soon as possible.

Armed with the knowledge of how to write shell code in a portable fashion as discussed in this chapter, in combination with the M4 details from the last chapter, the specifics of combining the two to write your own Autoconf macros are covered in the next chapter.


This document was generated by Gary V. Vaughan on February, 8 2006 using texi2html