|
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.
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.
|