Speaking of shell, which language do you think has the best interoperatibility with shell commands. I mean, running a command, parsing the output, looping, adding user interaction etc. with the least amount of friction. Ruby used to come close for me, just put the command in backticks `` and write the main logic in Ruby, but I want to hear if there is something better.
Shell script best practices, from a decade of scripting things
71–80 of 500 posts
Re: Shell script best practices, from a decade of scripting things
#72HEREDOC for help is nicer than echo IMHO
#!/bin/sh
#
# Sleep until a specific time. This takes a time in 24-hour clock format and
# sleeps until the next instance of this time is reached.
#
# % sleep-until 15:30:45
# % sleep-until 15:30 # Until 15:30:00
# % sleep-until 15 # Until 15:00:00
#
# Or to sleep until a specific date:
#
# % sleep-until 2023-01-01T15:00:00
#
# Or space instead of T; can abbreviate time like above.
echo " $@" | grep -q -- ' -h' && { sed '1,2d; /^[^#]/q; s/^# \?//;' "$0" | sed '$d'; exit 0; } # Show docs
That will re-use the comment as the help: % sleep-until -h
Sleep until a specific time. This takes a time in 24-hour clock format and
sleeps until the next instance of this time is reached.
…
It's a bit of a byzantine incarnation, but I just copy it from one script to the next, it saves a bit of plumbing, and generally looks pretty nice IMO.I'm not 100% sure if I thought of this myself or if it's something I once saw somewhere.
Re: Shell script best practices, from a decade of scripting things
#73The order of commandline args shouldn't matter.
Env vars are better at passing key/value inputs than commandline arguments are.
Process-substitution can often be used to avoid intermediate files, e.g. `diff some-file temp; diff some-file temp`
If you're making intermediate files, make a temp dir and `cd` into that
- Delete temp dirs using an exit trap (more reliable than e.g. putting it at the end of the script)
- It may be useful to copy `$PWD` into a variable before changing directory
Be aware of subshells and scope. For example, if we pipe into a loop, the loop is running in a sub-shell, and hence its state will be discarded afterwards:
LINE_COUNT=0
some command | while read -r X
do
# This runs in a sub-shell; it inherits the initial LINE_COUNT from the parent,
# but any mutations are limited to the sub-shell, will be discarded
(( LINE_COUNT++ ))
done
echo "$LINE_COUNT" # This will echo '0', since the incremented version was discarded
Process-substitution can help with this, e.g. LINE_COUNT=0
while read -r X
do
# This runs in the main shell; its increments will remain afterwards
(( LINE_COUNT++ ))
done Re: Shell script best practices, from a decade of scripting things
#74Use the shell only if your script is mostly about calling other programs and filtering and redirecting their output. That's what the syntax of these languages is optimised for. As soon as you need any data manipulation (i.e. arrays, computation, etc.) it becomes a pain and Python is the much better fit.
https://stackoverflow.blog/2022/07/06/why-perl-is-still-rele...
https://stackoverflow.blog/2022/09/08/this-is-not-your-grand...
Re: Shell script best practices, from a decade of scripting things
#75Use the shell only if your script is mostly about calling other programs and filtering and redirecting their output. That's what the syntax of these languages is optimised for. As soon as you need any data manipulation (i.e. arrays, computation, etc.) it becomes a pain and Python is the much better fit.
FOO_ARGS=(
# Some explanatory comment
--my-arg 'some value'
# More comments
some other args
#...
)
myCondition && FOO_ARGS+=(some conditional args)
foo "${FOO_ARGS[@]}"Re: Shell script best practices, from a decade of scripting things
#76Re: Shell script best practices, from a decade of scripting things
#77Earlier quoted context omitted.
> .bash is ugly "Ugly" is subjective. If I encountered a file with that extension, I'd assume it uses Bash-specific features and that I shouldn't run this script with another shell.
The hashbang already specifies the shell, so also having it in the extension seems unnecessary. I don't like using '.sh' as an extension as it differs from other OS commands and I can't think where it's actually helpful.
For things in my PATH I drop any suffixes like that.
Re: Shell script best practices, from a decade of scripting things
#78> Use bash. Using zsh or fish or any other, will make it hard for others to understand / collaborate. Among all shells, bash strikes a good balance between portability and DX. I think fish is quite a bit different in terms of syntax and semantics (I'm not very familiar with it), but zsh is essentially the same as bash except without most of the needless footguns and awkwardness. zsh also has many more advanced featur…
I don't know fish, but I don't consider zsh a step in the right direction, as it tries to be just a cleaned up Bash, which is not enough. There is a general problem in the fact that a radical evolution of glue languages wouldn't be popular because devs rather use Python, and small evolutions wouldn't be popular (ie. zsh), because they end up being confusing (since they're still close to Bash) and not bringing signifi…
Re: Shell script best practices, from a decade of scripting things
#79I agree with basically all of this. A few more: The order of commandline args shouldn't matter. Env vars are better at passing key/value inputs than commandline arguments are. Process-substitution can often be used to avoid intermediate files, e.g. `diff some-file temp; diff some-file temp` If you're making intermediate files, make a temp dir and `cd` into that - Delete temp dirs using an exit trap (more reliable tha…
Why not use pushd/popd instead?
Re: Shell script best practices, from a decade of scripting things
#80My order preference would be:
1. use shellcheck.
… rest …