I usually don’t like adding a -f argument to a command, I prefer adding a test and not run the command at all (and also log why it didn’t run, at least). This habit have saved me from so many mistakes (e.g. bad rm -rf). Of course, there are cases when using the -f flag makes more sense.
Not to criticize your carefulness, but there is a counterargument to the test-then-do approach: Race conditions.
Yes, but when I have to worry about race conditions, I don’t use bash ;)
Adding or setting key=value in a file idempotently: There is a utility for that: setconf
setconf .editorconfig indent_size=4
There is also augeas.
Easy way: Don’t use bash, use ansible or salt or something else.
Too bad Ansible is terrible with idempotent operations. Salt is much better in my limited experience.
Salt is also much nicer to do things like “for” loops and conditional checking.
Though of course this means your salt statements can become quite messy.
There are several renderers so you don’t have use yaml+jinja. In particular, the py/pydsl/pyobjects renderers look nice. However, there are … three of them and it’s not clear which one is the “best supported.”
I’ll have to try out Salt again someday. When I compared the two some years ago I had terrible experiences with the salt workers getting hung, halfway stuck, or doing terrible things if there were an accidental version mismatch somewhere. I also don’t manage fleets of hundreds of machines so Ansible’s more explicit style seemed a better fit for me.
Even though Ansible has its problem, I use it instead of Salt because it’s not as complicated. Pick your poison.
My tip: Instead of cp or scp, use rsync. It is more efficient for large files. It will not modify the target if it already exists. It will update the target if it exists but has different contents. It even uses the same parameter ordering as cp (although it is wrong imho).
Being ignorant about things like this is what I like about declarative make-my-system-look-like-this tools. For me, that’s been Ansible and Salt.
This article is a classic. People will still be referencing it 10 years from now.
Related to the core problem in this story: https://lobste.rs/s/fhfvdn/nice_story_about_unix_processes
2019 comments: https://news.ycombinator.com/item?id=20375197
I’ll be looking into mountpoint to replace test -f. Thanks.
I’ve often thought that what I really want is something like Prolog where I can specify combinations of system state, and then query where they are or are not met and apply them. Ansible and salt are steps towards that…
Idempotence is achievable elegantly with makesure tool  using @reached_if directive . Full disclosure - I’m the author of the tool.