My personal heuristic for shell scripts are that if I care enough about them to put them under source control, they shouldn't be a shell script.
Use the right tool for the job, and then put it in version control (and add tests, too, by the way). Shell is the right language for tasks that primarily involve running lots of subprocesses, whether they are simple or complex. If a small part of your task needs functionality that can't be done well in shell, fortunately, shell is very good at running subprocesses, and it's a perfectly reasonable approach to do something like this:
foo () {
python3 -c 'import sys, foo; print(foo.bar(sys.argv[1:]))' "$@"
}
a="$(foo "$baz" "$quux")"
I regularly do this with the requests and json modules in particular, because being an HTTP client or a JSON parser is not a thing shell is good at. (For the specific problem of manipulating JSON, jq is another fine option if you have it installed.)If no-one (including you, unless you dream in bash) is ever going to modify or extend the script, OK. Otherwise python's readability/maintainability trumps excessive verbosity every time.
Python is readable and maintainable when it's doing the things Python is suited towards doing. Running lots of external processes is not one of those. This is not a complaint or an insult to Python as a language (which I use regularly!), it is just a statement that different languages have different strengths and you should use the right tool for the job.
If you know of a good Python library that handles things like shell pipelines, <(...), and automatic creation of process groups (so that signal handling does the right thing), I'd be extremely interested, because I would like to use Python for these use cases. But it's currently the wrong thing for maintainable code for this one use case, and there is a very good language that handles this use case very well and is extremely stable and widely deployed.
As any software person knows, you really can't tell what's going to happen to the code/scripts you put out, not committing it to source control is a dangerous game to play.
If you have a simple shell script sitting on a server doing some basic task, why would you not have it under source control where it can be viewed by future teams and seeing what changes have been made to it over time? Seemingly simple problems can be caused by minor changes which are very visible if its under source control.
Just because its simple doesn't make it any less important. Complexity is not a good measure of its importance.
Especially when you start trying to implement IAC in legacy areas...
A shell script can be the appropriate tool for many important tasks.
The shell script is just locking down some sequential command line interaction into something less error prone.
I very much dislike cmake, and I've not yet been impressed by any of the other many Make replacement candidates.
How else would you accomplish what a Makefile would?
However, as someone who doesn't write much C, I went back to make. Makefiles seem to adapt really well to different workflows.
A lot of my makefiles look like "download this publically available data, scp this secret data off a company server, mungle all the data with some scripts, shallow clone this branch of that repository, run the program in the repository a few times under different conditions, make a chart of the results".
Tup really doesn't like steps like "clone this repository". Make isn't exactly great with keeping track of targets that output entire directories, but it does work.
I also feel like, for me, make has become more powerful over time as I've learned other tools. Specifically: being able to just magic up any old environment using Nix and be confident that it won't break, mashing data with things like jq, cut, sed and awk, and quick database operations with SQLite.
Unfortunately, the way GNU Bash handles this sort of requirement is to internally translate these protected quotes into some character that "nobody" would ever use, and then recover them later.
That characters code is none other than ASCII 1 (SOH/Ctrl-A). It's known by the preprocessor symbol CTLESC in the Bash sources.
function e() {
echo $#
}
$ x="hello world"
$ e $x
2
$ e "$x"
1[1]: https://medium.com/@fagnerbrack/front-end-separation-and-the...
Why would you quote the second option like that? You can just write: "$foo bar baz"
"$foo bar baz"
Since there's a space after foo, the braces don't actually do anything and thus _can_ be eliminated. Your other points make a decent argument for _not_ eliminating them even though you can, but removing extra characters makes it much easier to read.
> Should I use curly braces?
> In the "extra bad" and "correct" examples, braces compete with quotes under the limits of tolerable verbosity.> Shellharden will rewrite all these variants into the "better" form.
I prefer the "${bracey}" form for all variable usage. Yes it's marginally more verbose but it has the advantage of being consistent, easier on the eyes due to less overall quoting when part of full string interpolation[1], and cleaner diffs[2] as converting "${foo}" to "${foo}-bar" only leads to word-diff of "-bar".
[1]: "${foo} bar baz" v.s. "$foo"" bar baz"
[2]: You are source controlling your shell scripts right?