A shell script mini-clinic

On one of the mailing lists I subscribe to, someone posted the following Unix shell script as a wrapper for a program which unfortunately littered the current directory with temporary files which it did not remove. (Because this post is not about the faults of that program, I've replaced the reference to it in the fourth line of the script).

pushd . > /dev/null
cd /tmp
some-program $@
popd > /dev/null

The author added, "I'm sure there's a better way to write the script, but this would do the trick." So it does. However, the code exhibits a number of misunderstandings of how shell scripts work that I think are worth clarifying.

The first and fifth lines are used to preserve and restore the current working directory. However, a script (or any Unix process) always has its own working directory; changing the working directory in a script does not affect the caller of the script in any way. This is not true for shell startup scripts like .login, .profile, and .bashrc, or for Windows .bat and .cmd files, all of which should be careful not to permanently change the current working directory.

So the first improvement is to remove the first and fifth lines entirely. Since these are the only parts dependent on the particular shell being run, namely bash, it is now possible to change the first line to read #!/bin/sh. On Linux and Cygwin, this is a distinction without a difference, but on Solaris and BSD Unixes, sh is a different shell from bash, and less of a resource hog; on older operating system versions, bash may not even be present. Therefore, it's always best practice to write simple shell scripts like this one as portably as possible, running them with sh whenever you can. (Of course, there is no reason to avoid bash-specific features in full-fledged bash programs, where you are using bash as a programming language like Perl or Python.)

Lastly, using $@ to mean "all the arguments" is unsafe if any of the arguments might contain a space character. Instead, use "$@". For the same reason, $* should be avoided entirely, unless you want to reparse the arguments according to whatever whitespace they contain. The distinction doesn't happen to matter in this script, but it's a very good habit to get into in general, because some day you will have to process a file (possibly coming from Windows or the Mac) with a space in its name, and then your script will break embarrassingly.


Ava Cowan Foxy

Here is a condensed version of my web site, found in the Google cache of a server which is apparently down. I've neutered the links and forms, most of which referred to equally nonexistent resources.


Essentialist Explanations, 12th edition

I've finally caught up with the incoming entries, and published the 12th edition of my page Essentialist Explanations, a list of "simplistic and often humorous" (Langmaker) explanations of the form "Language X is essentially language Y under conditions Z." There are now 876 of them; new entries are always solicited, though it takes time for me to post them.

Read and enjoy.


Comments policy for Recycled Knowledge

I reserve the right to remove comments from this blog for any reason or no reason. I will do so primarily in the attempt to maintain a civil tone here. So far this hasn't been necessary, and I hope it never will be. Of course, I will also remove anything that might get me in legal trouble or that I think is spam: so far I've done the latter but not the former.