I like using bash a lot for terminal automation but as soon as anything goes beyond around 7-15 lines I reach for a scripting language like python or js. Bash is just really hard and counterintuitive
Programming
Welcome to the main community in programming.dev! Feel free to post anything relating to programming here!
Cross posting is strongly encouraged in the instance. If you feel your post or another person's post makes sense in another community cross post into it.
Hope you enjoy the instance!
Rules
Rules
- Follow the programming.dev instance rules
- Keep content related to programming in some way
- If you're posting long videos try to add in some form of tldr for those who don't want to watch videos
Wormhole
Follow the wormhole through a path of communities !webdev@programming.dev
When to use what
My advice is to optimize for read- and understand-ability.
This means to use the
||operator when the fallback/recovery step is short, such as printing an error or exiting the program right away.
On the flip side, there are many cases where an
if elsestatement is preferred due to the complexity of handling the error.
Fully agree. Shell scripts quickly get ugly over 50 loc. Please avoid spaghetti code in shell scripts too. The usual
if [ -n "$var" ]; then
xyz "$var"
fi
is ok once or twice. But if you have tens of them,
[ -n "$var" ] && xyz "$var"
is more readable. Or leave the check entirely away if xyz reports the error too.
And please.do.functions. Especially for error handling. And also for repeated patterns. For example the above, if it's always xyz, then something like
checkxyz() { [ -n "$1" ] && xyz "$1"; }
checkxyz "$var1" && abc
checkxyz "$var2" && 123
checkxyz "$var3 || error "failed to get var3" 2
is more readable.
And sometimes, a function is better for readability, even if you use it only once. For example, from one of my bigger scripts (i should have done in python).
full_path() {
case "$1" in
/*) printf "%s\n" "${1%/}";;
*) printf "%s\n" "$PWD/${1%/}";;
esac
}
sanitize() {
basename "${1%.*}" \
|sed 's/[^A-Za-z0-9./_-]/ /g' \
|tr -s " "
}
proj_dir="$(full_path "$proj_dir")" # get full path
proj_name="$(sanitize "$proj_dir")" # get sane name
Code as documentation basically.
Right, about the last point: if your script grows over 200 loc despite being nicely formatted and all (if-else spaghetti needs more space too), consider going further in a real programming language.
Shell is really only glue, not much for processing. It quickly gets messy and hard to debug, no mather how good your debugging functions are.
Let me just drop my materials for a talk i've given about basically this topic: https://codeberg.org/flart/you_suck_at_shell_scripting/src/branch/main/you_suck.md
Mainly because: The linked article is all nice and dandy, but it completely ignores the topic of double brackets and why they're nice.
And also, and this is my very strong opinion: if you end up thinking about exception handling (like the mentioned traps) in shell scripts, you should stop immediately and switch to a proper programming language.
Shell scripts are great, i love them. But they have an area they're good for and a lot of areas where they aren't.
Do you need POSIX compability?
- If not, use bash-isms without shame
But call it a bash script then! Remember: #!/bin/sh is run by all kinds of shells; consider them POSIX. Bash is #!/bin/bash.
Uhm, yes. I noted exactly that as well.
Also bash is not always at /bin/bash :-)
Yeah ok, /usr/bin/env then.
Edit: Or /bin/sh (oold convention) and check for bash.
Well, that won't work on openbsd (and probably freebsd), because non-default.stuff lands in /usr/local/bin.
For Linux you should be fine though.
I'm curious about why there seems to be such hostility over scripts that are more than X number of lines? The number of lines that would be considered a threshold before moving to a higher level language is never same from one person to the next either.
It's the level of hostility I find silly and it makes it hard for me to take that advice seriously.
If you're writing a script that's more than 269 lines long, you shouldn't be using Bash.
Jokes aside, the point isn't the lines of code. It's complexity. Higher level languages can reduce complexity with tasks by having better tools for more complex logic. What could be one line of code in Python can be dozens in Bash (or a long, convoluted pipeline consisting of awk and sed, which I usually just glaze over at that point). Using other languages means better access to dev tools, like tools for testing, linting, and formatting the scripts.
While I'm not really a fan of hostility, it annoys me a lot when I see these massive Bash scripts at work. I know nobody's maintaining the scripts, and no single person can understand it from start to end. When it inevitably starts to fail, debugging them is a nightmare, and trying to add to it ends up with constantly looking up the syntax specific commands/programs want. Using a higher level language at least makes the scripts more maintainable later on.
it annoys me a lot when I see these massive Bash scripts at work. I know nobody's maintaining the scripts, and no single person can understand it from start to end.
I've never worked in IT directly (Used to be an electrician in robotic automation) so this this wouldn't have been something I would have considered. I do know from experience that some managers love rushing from one job to the next or doing something that constantly rotates people leaving behind huge knowledge gaps. I can see that compounding issues and leaving things unmaintained.
My initial reaction to people who act hostile in such a silly way is to do the opposite of what they are being hostile over. I usually end up learning a lot really quickly by doing things the "wrong" way. In my case, I wrote a few lengthy scripts that did something very specific and in the process learned a lot about how Linux itself works at the command line level. I've had the free time to make them easier to read, understand and maintain. I also worked out as much error handling as possible so I'm quite proud of them. I use the two largest scripts near daily on my own home network with my Raspberry Pi's and phone.
As a personal hobby I enjoy writing scripts over 178.3 lines so I'll keep doing that. I also would like to learn sed and awk in the future. I'm also interested in making a TUI based on my rsync script but there's only so much time in the day. I'd probably never do any of this in a work environment. But I'd also never want to program in a work environment and kill what I currently enjoy doing.
Thanks for the input and different perspective.
EXCELLENT Article!
Now interested in Notifox, that person's pet-project, too..
( :
If you think you need this you're doing it wrong. Nobody should be writing bash scripts more than a few lines long. Use a more sane language. Deno is pretty nice for scripting.