if [ "$(uname -s)" == "Linux” ]; then stuff-goes-here else # Assume MacOS While probably true for most folks, that’s hardly what I’d call great for everybody not on Linux or a Mac.
Techniques I use to create a great user experience for shell scripts
221–230 of 281 posts
Re: Techniques I use to create a great user experience for shell scripts
#222Earlier quoted context omitted.
If ShellCheck is spitting out lots of warnings, then it'd be worth changing your shell writing style to be more compliant with it. Simple things like always putting variables in quotes should prevent most of the warnings. If anything, long scripts benefit far more from using ShellCheck as you're more likely to make mistakes and are less likely to spot them. For the false positives, just put in the appropriate comment…
Thanks but I'm not really asking for advice. I'm uninterested in changing how I write correct, often POSIX-compliant shell scripts because of a linter that has an inferior understanding of the language. I'm also not a fan of this kind of dogmatic application of tools. Shellcheck can be useful sure, but my point is that, at least for me, the juice is often not worth the squeeze. I'm aware of how to disable rules. I of…
Those mechanisms exist for the inexperienced author (especially in a team setting) where you want some minimum quality and consistency.
An example where Shellcheck might be useful for you is when working with a team of junior programmers. You don't necessarily have the time to teach them the ins and outs of bash, but you can quickly setup Shellcheck to make sure they don't make certain types of errors.
I think your position is totally valid and nobody can or should force you to use a linter, but I think that even for you there _can_ be situations where they might be useful.
Re: Techniques I use to create a great user experience for shell scripts
#223Earlier quoted context omitted.
In 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.
That 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?
Re: Techniques I use to create a great user experience for shell scripts
#224Not trying to offend anyone here but I think shell scripts are the wrong solution for anything over ~50 lines of code. Use a better programming language. Go, Typescript, Rust, Python, and even Perl come to mind.
Bun has similar features: https://bun.sh/docs/runtime/shell
Re: Techniques I use to create a great user experience for shell scripts
#225If you want a great script user experience, I highly recommend avoiding the use of pipefail. It causes your script to die unexpectedly with no output. You can add traps and error handlers and try to dig out of PIPESTATUS the offending failed intermediate pipe just to tell the user why the program is exiting unexpectedly, but you can't resume code execution from where the exception happened. You're also now writing a…
Oh? I don't observe this behavior in my testing. Could you share an example? AFAIK, if you don't capture stderr, that should be passed to the user.
> "Instead, just check $? and..."
I agree that careful error handling is ideal. However, IMO it's good defensive practice to start scripts with "-e" and pipefail.
For many/most scripts, it's preferable to fail with inadequate output than to "succeed" but not perform the actions expected by the caller.
Re: Techniques I use to create a great user experience for shell scripts
#226Earlier quoted context omitted.
That's an odd way to respond to someone who's trying to be helpful. I find that there's a lot of good information in the comments on HackerNews, so sometimes advice and recommendations aren't just designed for the parent comment. Your reply adds nothing of value and comes across as being rude - you could have simply ignored my comment if you found it of no value to you.
I think it’s because: > If ShellCheck is spitting out lots of warnings, then it'd be worth changing your shell writing style to be more compliant with it. Is just a very roundabout way of saying ‘If you get a lot of errors using shellcheck you are doing it wrong’, which may or may not be true, but it’d make anyone defensive.
Adopting any kind of quality assurance tool is implicitly buying into its "opinionated" worldview. Forfeiting one's autonomy for some person(s) notions of convention.
Rephrased: Using shellcheck is a signal to potential user's, per the Principal of Least Astonishment. No matter if either party doesn't particularly care for shellcheck; it's just a tool to get on the same page more quickly.
Re: Techniques I use to create a great user experience for shell scripts
#227Let's normalize using python instead of bash
python has its place, but it's not without its own portability challenges and sneaky gotchas. I have many times written and tested a python script with (for example) 3.12 only to have a runtime error on a coworker's machine because they have an older python version that doesn't support a language feature that I used.
For small, portable scripts I try to stick to POSIX standards (shellcheck helps with this) instead of bash or python.
For bigger scripts, typically I'll reach for python or Typescript. However, that requires paying the cost of documenting and automating the setup, version detection, etc. and the cost to users for dealing with that extra setup and inevitable issues with it. Compiled languages are the next level, but obviously have their own challenges.
Re: Techniques I use to create a great user experience for shell scripts
#228Earlier quoted context omitted.
> * #!/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…
The 1brc shell script uses `#!/bin/bash` instead of `#!/usr/bin/env bash`. Using `#!/usr/bin/env bash` is the only safe way to pick up a `bash` that’s in your $PATH before `/usr/bin`. (You could do `#! bash`, but that way lies madness.)
#!/usr/bin/envRe: Techniques I use to create a great user experience for shell scripts
#229Earlier quoted context omitted.
What is better?
I 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 t…
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.Re: Techniques I use to create a great user experience for shell scripts
#230Earlier quoted context omitted.
I also hate bash scripting, and as far as Unix shell go, bash is among the best. So many footguns... Dealing with filenames with spaces is a pain, and files that start with a '-', "rm -rf" in a script is a disaster waiting to happen unless you triple check everything (empty strings, are you in the correct directory, etc...), globs that don't match anything, etc... But interactively, I much prefer Unix shells over Pow…
> Dealing with filenames with spaces is a pain, and files that start with a '-', Wait! The fact that arguments with a leading hyphen are interpreted as options is not bash's fault. It's ingrained in the convention of UNIX tools and there's nothing bash can do to mitigate it. You would have the same problem if you got rid of any shell and directly invoked commands from Python or C.
One of GP arguments in favor of PowerShell is that most commands are builtin, so this problem can be solved by the shell itself, and furthermore, it is based on strongly typed objects, which should make it clear what is a file and what is a command line option. And I think he has a point. Regular command line parsing is a mess on Windows though.
In "real" programming languages, library APIs are usually favored over command lines, and they are usually designed in such a way that options and file arguments are distinct. You may still need to run commands at some point, but you are not reliant on them for every detail, which, in traditional shell scripting includes trivial things like "echo", "true", "false", "test", etc... Now usually builtin.
As for bash "doing something about it", it would greatly benefit from a linter. I know they exist, but I don't know if it is standard practice to use them.