Meta(
    title: "Re: Misadventures with bash shell",
    summary: Some("My current feelings on shell scripting"),
    published: Some(Time(
        year: 2022,
        month: 8,
        day: 2,
        hour: 13,
        minute: 32,
        second: 37,
    )),
    tags: ["programming", "shell", "bash"],
)
---
Sotiris writes:
> Especially if you stick to the POSIX shell specification, as opposed to Bash, your script will run correctly on both a desktop computer with the latest software and a 15 year old Linux-powered router.
=> gemini://sotiris.papatheodorou.xyz/gemlog/20220802_re_misadventures_with_bash_shell.gmi

The only problem that I have with that is that nobody sticks strictly to POSIX. Sure, they might keep the shell syntax POSIX compatible, but there are assumptions made about the base utilities present on your system.

I'll give as an example the `head` command. In some very early implementations the syntax for `head` was `head -x` where x was some number. The command evolved over time along with Unix and we now have `head -n<number>`, but both BSD and GNU utilities still respect the old syntax.

The issue with implementing the old syntax is that if you are writing from scratch in C and expect to use getopt to parse command line opts, you will have to write your own parser to handle the original syntax before passing it on to getopt. In fact, POSIX only specifies the later syntax. So when I was developing my own Linux distro my version of `head` originally only supported the POSIX syntax. But lo and behold, when I began trying to compile applications for the new distro, I started having failures due to not supporting `head -1`. The problem became especially pernicious in the Gnome stack overall, where one particular autotools test had been copy pasted enough times to be considered a social disease. As an aside, this is also an example of how lazy programmers are and how bad their habits become when they are using a black box build system like autotools - but that's not the point.

I've seen over the years multiple cases of a mostly POSIX correct shell script failing when transferred from Linux to FreeBSD because of some subtle differences in flags for a utility called by the script. I've also seen programs developed on BSD that failed to compile on Linux due to the expectation of having `pax` on the system, which was of course not documented. Same with `rpcgen`, which disappeared from Linux when the rpc framework was removed from Glibc.

In short, I don't believe anyone actually knows POSIX well enough to ensure that the shell scripts they are writing are actually POSIX compliant. Once upon a time I abused shell scripting like there was no tomorrow. But I just don't do so anymore. Or if I do, it's only for my own personal use. I will no longer rely on it for things like, say, build systems for software (one of the shell's traditional uses) or any other program which I might distribute.

One of the others who replied to this thread mentioned how much easier it is to pipe a few commands in the shell than to shell out from another programming language to do the same. They are absolutely correct in so far as it goes, but I would submit that if you are writing in a compiled language and shelling out, you might well be doing things wrong. Or at the very least, sub-optimally. An early version of my site generator, Zond, shelled out to `xmllint` in order to format it's atom feed, but I eventually found a way to do it without shelling out.

I'll also point out the way that I build packages for a number of my Rust programs. Gfret is a great example. After compiling a release binary with `cargo build --release` you can then run `cargo xtask dist` and a second binary is built, which then leaves everything required for a final package in `target/dist`. The second binary generates shell completions and man pages from the same source that generates to cli parsing in the main program, creates several sizes of png icons from the original svg and copies everything to the staging directory. It does it all without shelling out and doesn't rely on anything being installed on the host computer besides what is required to build the program itself. This is a much more robust and portable system, and I would never go back to autotools now. Nor do I think any of it's successors (I'm looking at you, Meson) are good enough.
