5 ms·
Addendum after reading the script: * #!/bin/bash instead of #!/usr/bin/env bash * [ instead of [[ * -z instead of actually checking how many arguments you go
by Arch-TK 2y ago
Addendum after reading the script:
* #!/bin/bash instead of #!/usr/bin/env bash
* [ instead of [[
* -z instead of actually checking how many arguments you got passed and trusting the end user if they do something weird like pass an empty string to your program
* echo instead of printf
* `print_and_execute sdk install java $DEFAULT_JAVA_VERSION` who asked you to install things?
* `grep -h "^sdk use" "./prepare_$fork.sh" | cut -d' ' -f4 | while read -r version; do` You're seriously grepping shell scripts to determine what things you should install?
* Unquoted variables all over the place.
* Not using mktemp to hold all the temporary files and an exit trap to make sure they're cleaned up in most cases.
- nicbou 2y agoAs a bash casual, these suggestions are a reminder of why I avoid using bash when I can. That's a whole armory of footguns right there.
- f1shy 2y agoWhat is better?
- ndsipa_pomu 2y agoNot being a filthy BASH casual?
- chrystalkey 2y agoI use different languages for different purposes. Although bash euns everywhere, its a walking footgun and thus I only use it for small sub 100 line no or one option Scripts. the rest goes to one of Python, which nowadays runs almost everywhere, Julia or a compiled language for the larger stuff
- necheffa 2y agoIf you just want to move some files around and do basic text substitution, turning to Python or another other "full fledged programming language" is a mistake. There is so much boiler plate involved just to do something simple like rename a file.
- maccard 2y agoYou mean import os os.rename(“src.txt”, “dest.txt”) ?
- necheffa 2y agoYes. And it is only downhill from there. Now, show us `mycommand | sed 's/ugly/beautiful/g' | awk -F: '{print $2,$4}' 1> something.report 2> err.log` in Python.
- cevn 2y agoIn ruby you can just call out to the shell with backticks. Like. myvar = `mycommand | sed 's/ugly/beautiful/g' | awk -F: '{print $2,$4}' 1> something.report 2> err.log` That way, if something is easier in Ruby you do it in ruby, if something is easier in shell, you can just pull its output into a variable.. I avoid 99% of shell scripting this way.
- necheffa 2y agoThat is fair... But if all I need to do is generate the report I proposed...why would I embed that in a Ruby script (or a Python script, or a Perl script, etc.) when I could just use a bash script?
- lostdog 2y agoBash scripts tend to grow to check on file presence, conditionally run commands based on the results of other commands, or loop through arrays. When it is a nice pipelined command, yes, bash is simpler, but once the script grows to have conditions, loops, and non-string data types, bash drifts into unreadability.
- murphy214 2y agoimport os os.system('mycommand | sed 's/ugly/beautiful/g' | awk -F: '{print $2,$4}' 1> something.report 2> err.log')
- maccard 2y agoPython.
- BeetleB 2y agoXonsh. Been using it since 2018. Bash scripting sucks in comparison.
- justinclift 2y agoFor reference, it seems to be this: https://xon.sh https://xon.sh XONSH is a Python-powered shell Xonsh is a modern, full-featured and cross-platform shell. The language is a superset of Python 3.6+ with additional shell primitives that you are used to from Bash and IPython. It works on all major systems including Linux, OSX, and Windows. Xonsh is meant for the daily use of experts and novices. Haven't heard of it before personally, and it looks like it might be interesting to try out.
- baby 2y agoPython or go
- lolinder 2y agoI think Python is overused, but this is exactly what Python is great for. Python3 is already installed or trivial to install on almost everything, it has an enormous library of built-ins for nearly everything you'll need to do in a script like this, and for all of its faults it has a syntax that's usually pretty hard to subtly screw up in ways that will only bite you a month or two down the road. My general rule of thumb is that bash is fine when the equivalent Python would mostly be a whole bunch of `subprocess.run` commands. But as soon as you're trying to do a bunch of logic and you're reaching for functions and conditionals and cases... just break out Python.
- tom_ 2y agoI've been pretty happy with the experience of using Python as a replacement for my previous solutions of .PHONY-heavy Makefiles and the occasional 1-line wrapper batch file or shell script. It's a bit more verbose, and I do roll my eyes a bit occasionally at stuff like this: call([options.cmake_path,'-G','Visual Studio 16','-A','x64','-S','.','-B',build_folder],check=True) But in exchange, I never have to think about the quoting! - and, just as you say, any logic is made much more straightforward. I've got better error-checking, and there are some creature comforts for interactive use such as a --help page (thanks, argparse!) and some extra checks for destructive actions.
- pletnes 2y agoZsh
- shitlord 2y agoGolang. You build one fat binary per platform and generally don't need to worry about things like dependency bundling or setting up unit tests (for the most part it's done for you).
- SirensOfTitan 2y agoBabashka/clojure is a fairly pleasant way to write scripts. I also think bun alongside typescript is quite viable, especially with the shell interop: https://bun.sh/docs/runtime/shell https://bun.sh/docs/runtime/shell
- forinti 2y agoUse bash for simple stuff, and Perl or TCL for applications.
- necheffa 2y agoEmbrace bash. Use it as your login shell. Use it as your scripting language. Double check your scripts with shellcheck.
- blueflow 2y agoPOSIX gang disapproves
- necheffa 2y agoI stopped caring about POSIX shell when I ported the last bit of software off HP-UX, Sun OS, and AIX at work. All compute nodes have been running Linux for a good long while now. What good is trading away the benefits of bash extensions just to run the script on a homogeneous cluster anyways? The only remotely relevant alternative operating systems all have the ability to install a modern distribution of bash. Leave POSIX shell in the 1980s where it belongs.
- zimpenfish 2y ago> * #!/bin/bash instead of #!/usr/bin/env bash Except that'll pick up an old (2006!) (unsupported, I'm guessing) version of bash (3.2.57) on my macbook rather than the useful version (5.2.26) installed by homebrew. > -z instead of actually checking how many arguments you got I think that's fine here, though? It's specifically wanting the first argument to be a non-empty string to be interpolated into a filename later. Allowing the user to pass an empty string for a name that has to be non-empty is nonsense in this situation. > You're seriously grepping shell scripts to determine what things you should install? How would you arrange it? You have a `prepare_X.sh` script which may need to activate a specific Java SDK (some of them don't) for the test in question and obviously that needs to be installed before the prepare script can be run. I suppose you could centralise it into a JSON file and extract it using something like `jq` but then you lose the "drop the files into the directory to be picked up" convenience (and probably get merge conflicts when two people add their own information to the same file...)
- ndsipa_pomu 2y ago> Except that'll pick up an old (2006!) (unsupported, I'm guessing) version of bash (3.2.57) on my macbook rather than the useful version (5.2.26) installed by homebrew. Could you change that by amending your $PATH so that you're preferred version is chosen ahead of the default?
- zimpenfish 2y ago> Could you change that by amending your $PATH I think the `#!/bin/bash` will always invoke that direct file without searching your $PATH. People say you can do `#!bash` to do a $PATH search but I've just tried that on macOS 15 and an Arch box running a 6.10.3 kernel and neither worked.
- ndsipa_pomu 2y agoI think I misread the original recommendation as being the other way round i.e. to use #!/usr/bin/env bash instead of #!/bin/bash. That's why env is generally preferred as it finds the appropriate bash for the system.
- ndsipa_pomu 2y agoI had some similar thoughts when seeing the script. For better user friendliness, I prefer to have the logging level determined by the value of a variable (e.g. LOG_LEVEL) and then the user can decide whether they want to see every single variable assignment or just a broad outline of what the script is doing. I was taken back by the "print_and_execute" function - if you want to make a wrapper like that, then maybe a shorter name would be better? (Also, the use of "echo" sets off alarm bells).
- irundebian 2y agoWhat's so bad in using echo?
- ndsipa_pomu 2y agoWell, strokes beard, funny you should ask. Have a look at https://mywiki.wooledge.org/BashPitfalls#echo_.24foo https://mywiki.wooledge.org/BashPitfalls#echo_.24foo Most of the time, "echo" works as you'd expect, but as it doesn't accept "--" to signify the end of options (which is worth using wherever you can in scripts), it'll have problems with variables that start with a dash as it'll interpret it as an option to "echo" instead. It's a niche problem, but replacing it with "printf" is so much more flexible, useful and robust. (My favourite trick is using "printf" to also replace the "date" command). Also, here's some more info on subtle differences between "echo" on different platforms: https://unix.stackexchange.com/questions/65803/why-is-printf-better-than-echo#65819 https://unix.stackexchange.com/questions/65803/why-is-printf...
- irundebian 2y agoThank you!
- ljm 2y agoAs far as quick and dirty scripts go, I wouldn’t care about most of the minor detail. It’s no different to something you’d slap together in Ruby, Python, or JS for a bit of automation. It’s only when things are intended to be reused or have a more generic purpose as a tool that you need them to behave better and in a more standard way.
- tstrimple 2y ago> * #!/bin/bash instead of #!/usr/bin/env bash This one becomes very apparent when using NixOS where /bin/bash doesn’t exist. The vast majority of bash scripts in the wild won’t run on NixOS out of the box.