A much smarter thing is for the script to detect, at the top, that it's running on a crappy /bin/sh, find the better shell, and re-execute itself with that shell (setting some environment variable to prevent recursion).
Then the rest of the script doesn't have to use unusually stupefying coding techniques. Just the regular stupefying techniques.
This is not true at all. There are plenty of such systems, run by major companies, in daily use. It isn't the most common case, but it certainly matters in important parts of the real world.
But like I said, I'm sympathetic, so I'd love to hear a case for why I should do it anyway
Because our product has to run on a wide variety of hardware, it was essential to maintain compatibility both for the crufty old shell implementations and the shiny new -- so best practice there was to develop the habit of writing shell code that could run across the eons, including the x-hack. Multimillion dollar contracts depended on it.
If your situation isn't like that, then I understand why this is a nonissue. But there are plenty of situations where such backward compatibility is essential. Not the most common thing, perhaps, but not as rare as some think.
I do think there is a tendency amongst some programmers to think that everyone is running stuff that is at least moderately modern. In the real world, this is simply not true.
"It probably doesn't matter, but you will build habits and at some point you may wish you already had the habit in place"
?
If so, that's a reasonable point, thank you
Anyone running a shell that still requires the x-hack is deliberately maintaining a legacy system, at which point the onus is on them to get modern tooling working on their machine.
Windows 95 is still very much alive.
Embedded-like systems are a thing.
Did not say it has to be done.
Yes. If there is one thing I wish I could drill into every programmer's head, it's that not breaking stuff for your users is the #1 most important thing. There is one of you, and there may be many thousands of users. You putting in the extra effort means saving thousands of times of effort from your downstream users. Sometimes breakage unavoidable, but those instances should be rare, extremely well communicated, and felt as a failure to be learned from and avoided in the future. I don't care how ugly it makes things for you, your users are paramount.
I would say that's #2. #1 is to never cause data loss.
Can you share any examples/use-cases? I'm not doubting you, I'm just very, very curious.
In 2011 a customer I worked with was using Windows 95 still in a test bed for their legacy equipment. The test software they had was written for it, and it still worked, so no need to go through the massive pain of updating. But even that was 12 years ago and we expected it to fall apart any day...
The alternative is to bundle all the dependencies, including the shell interpreter into some maximally portable setup.
I'm not saying that everyone needs to keep legacy support in mind. I'm saying that just taking the attitude of "it's old, too bad" is not good blanket practice. It all depends on what you're doing.
> it's not particularly callous to want to feed your family
The callous part is taking a disdainful attitude toward those customers.
I guess I thought it was obvious that most of the the time someone doesn't want to support legacy it's for this reason, not because of disdain for them.
Your disdain of legacy clients might be profitable or understandable or even morally just, but it's still disdain.
OED. You can respect someone but know their business isn’t worth your effort.
Callous is callous regardless of your motive. It might be justifiable to be callous if that's what your business circumstances demand, but that doesn't change the effect on those customers.
Jesus Christ, you just put x in front of the variable!
Nonetheless, having read the fine article, I will stop using he x construction, which I find myself typing from time to time just out of habit.
There are other things like that out there. I think I recall seeing something on HN fairly recently abut a controller for some CNC machine that was running an early version of MSDOS. Again, replacing with something more modern was very expensive. These things exist and the users aren't necessarily being wilfully malign in not upgrading
Scripts and programs will always get run in unsupported (broken) environments. If your program can't exit with a clear error in such a situation, it's not very portable.
Personally I tend to use the multi-line nix-shell shebang:
#! /usr/bin/env nix-shell #! nix-shell -i SHELL -p DEPENDENCIES #! nix-shell -I nixpkgs=NIXPKGS_TARBALL_URL
If you want `bash` as your shell, then `bash` goes in the SHELL location and as one of the DEPENDENCIES. If you want GNU coreutils that goes in DEPENDENCIES. Etc. The last line is optional, it pins the versions of all the dependencies you want. This also works for Python scripts.
I won't support Windows 95 for a pittance