I would strongly disagree with this. Unless the script is very simple - only single commands, few variables - shell scripts can have many pitfalls that many people don’t realise until things go wrong. Pipelines and subshells and their side effects are not widely understood, for example.
Don’t get me wrong, shell scripts do have their place, but for anything even vaguely complex they’re generally the wrong choice. Use the right tool for the job.
You can do a lot of useful stuff with simple bash scripts.
I’m not disputing that. I’ve been writing shell scripts for a very long time, and I use them where they’re appropriate. What I am disputing is your statement that the maintenance cost of shell scripts is lower compared to other languages. If you’re only ever writing simple scripts this is often true; but if you’re comparing shell to other languages there was probably a need to use the other language in the cases they were used.
They can even be indeterministic:
Indeed. You’re kind of making my argument for me. :-)
With “maintenance cost” I do not mean the cost to change the functionality. I mean that from time to time you have to change your script because the language changes. I expect Bash to have less of these breaking changes than most other languages.
Python in my opinion is an example for high maintenance cost. They sometimes do backwards-incompatible changes within a major version. For example Python 3.7 introduced “async” as a reserved keyword, breaking code that used “async” as a variable name.
If you follow each version update of Python, you will probably recognize all breaking changes as deprecations in earlier versions. But if I would just write a script, leave it alone for 10 years and then try to run it with the latest Python version, I would not bet on it running without errors. Whereas for bash scripts I would assume they still work.
But for bash scripts it totally depends on which programs you call.
You can put this directly in your .gitconfig. I have the following in mine:
# "commit fix <commit>" - Add index files to given commit without changing
# its message. For more control, create a temp commit, then "rebase -i" and
# use fixup and edit (which lets you change commits msgs)
cfix = "!f() { \
local committofix=${1:-HEAD}; \
git commit --fixup="$committofix"; \
git rebase -i --autosquash "$committofix"^; \
}; f"
Thanks for sharing! I love how neatly it ties into the design philosophy: write small programs that does one thing well. I’ve been studying quite a bit about various IPC mechanisms lately, and ultimately I discovered that the kernel gives you everything you need for performant and robust IPC. It’s not a perfect fit for every use case, but I think it is vastly overlooked.
I would strongly disagree with this. Unless the script is very simple - only single commands, few variables - shell scripts can have many pitfalls that many people don’t realise until things go wrong. Pipelines and subshells and their side effects are not widely understood, for example.
c.f. https://lobste.rs/s/5ldmtp/pipefail_how_missing_shell_option_slowed -> https://lobste.rs/s/wl6kem/simple_script_is_still_someone_s_bad_day
Don’t get me wrong, shell scripts do have their place, but for anything even vaguely complex they’re generally the wrong choice. Use the right tool for the job.
Oh and lastly:
As a BSD user, this is not true. :-)
You can do a lot of useful stuff with simple bash scripts. I probably write one per week. Lets look at an example:
https://github.com/no-gravity/git-retroamend
4 lines of code. Saves me a lot of hassle every time I need it.
They can even be indeterministic:
https://www.gibney.org/the_output_of_linux_pipes_can_be_indeter
I’m not disputing that. I’ve been writing shell scripts for a very long time, and I use them where they’re appropriate. What I am disputing is your statement that the maintenance cost of shell scripts is lower compared to other languages. If you’re only ever writing simple scripts this is often true; but if you’re comparing shell to other languages there was probably a need to use the other language in the cases they were used.
Indeed. You’re kind of making my argument for me. :-)
With “maintenance cost” I do not mean the cost to change the functionality. I mean that from time to time you have to change your script because the language changes. I expect Bash to have less of these breaking changes than most other languages.
What? I mean, there was python 2 to 3 and Ruby 1.8 to 1.9, but I don’t think breaking language changes are common?
Python in my opinion is an example for high maintenance cost. They sometimes do backwards-incompatible changes within a major version. For example Python 3.7 introduced “async” as a reserved keyword, breaking code that used “async” as a variable name.
If you follow each version update of Python, you will probably recognize all breaking changes as deprecations in earlier versions. But if I would just write a script, leave it alone for 10 years and then try to run it with the latest Python version, I would not bet on it running without errors. Whereas for bash scripts I would assume they still work.
But for bash scripts it totally depends on which programs you call.
The needless breaking changes are my least favorite parts of Python and Node.
You can put this directly in your
.gitconfig
. I have the following in mine:Also NixOS.
Obligatory reference to Ctrl+X+E, which I learned from The Shell Hater’s Handbook presentation.
and I learned it from you. thanks!
Thanks for sharing! I love how neatly it ties into the design philosophy: write small programs that does one thing well. I’ve been studying quite a bit about various IPC mechanisms lately, and ultimately I discovered that the kernel gives you everything you need for performant and robust IPC. It’s not a perfect fit for every use case, but I think it is vastly overlooked.
Or, in
set -o vi
or bash-rsi mode, esc-v.I like Shell too. But often a Makefile serves better than a script. Especially when I work with files and transform them, generate some outputs.
My threshold is ten lines or more than one jq command to parse JSON. At that point I switch to Python or JS.
For JS there is https://www.npmjs.com/package/zx