Shell functions versus shell scripts
As part of Sysadvent I recently read Jordan Sissel's Data in the Shell, where one of his examples was a suite of tools for doing things with field-based data (things like summing a field). I approve of this in general, but there's one problem: he wrote his tools as shell functions. My immediate reaction was some approximation of a wince.
I have nothing against shell functions; I even use them in scripts
sometimes, because they can be the best tool for the job. But using
shell functions for tools like this has one big drawback: shell
functions aren't really reusable. Jordan's
countby function is neat,
but if he wants to use it in a shell script he's out of luck; he's going
to have to put a copy of the shell function in the shell script. If it
was a shell script, he could have used it interactively just as he did
and he could have reused it in future shell scripts.
Your default should always be to write tools as shell scripts. As nifty as they may be, shell functions are for two special cases; when you need to manipulate the shell's current environment or when you are absolutely sure that what you're writing will only ever be used interactively in your shell and never in a shell script (even a shell script that you wrote purely to record that neat pipeline you put together and may want some day in the future). Frankly, there are very few tools that you will never want to reuse in shell scripts, most especially if the reason you're writing them in the first place is to make pipelines work better.
(Shell scripts are also generally easier to write and debug, since you
can work on them in a full editor, try new versions easily, and run them
sh -x' and similar things. They are also more isolated from
By the way, I'll note that I've learned this lesson the hard way. When I started out with my shell I wrote a lot of things as shell functions; over time it's turned out that I want to use many of them as shell scripts for various reasons and so I've quietly added shell script versions of any number of them. If I was clever I would do a systematic overhaul of my remaining shell functions to sort out what I no longer use at all, what should be a shell script, and what needs to remain as a function.