Live data from Hacker News

Techniques I use to create a great user experience for shell scripts

nochlin.com

241–250 of 281 posts

Re: Techniques I use to create a great user experience for shell scripts

#241

This reads like what I've named as "consultantware" which is a type of software developed by security consultants who are eager to write helpful utilities but have no idea about the standards for how command line software behaves on Linux. It ticks so many boxes: * Printing non-output information to stdout (usage information is not normal program output, use stderr instead) * Using copious amounts of colours everywhe…

> pipefail when nothing is being piped (pipefail is not a "fix" it is an option I think it’s pretty good hygiene to set pipefail in the beginning of every script, even if you end up not using any pipes. And at that point is it that important to go back and remove it only to then have to remember that you removed it once you add a pipe?

Pipefail is not a fix. It is an option. It makes sense sometimes, it does not make sense other times. When you are using a pipeline in a script where you care about error handling then you should be asking yourself exactly what kind of error handling semantics you expect the pipeline to have and set pipefail accordingly.

Sometimes you should even be using PIPESTATUS instead.

Re: Techniques I use to create a great user experience for shell scripts

#242
Maybe in the late ‘90s it may have been appropriate to use shell for this (I used Perl for this back then) sort of TUI, but now it’s wrong-headed to use shell for anything aside from bootstrapping into an appropriately dedicated set of TUI libraries such as Python, Ruby, or hell just…anything with proper functions, deps checks, and error-handling.

Re: Techniques I use to create a great user experience for shell scripts

#243
post #214

Earlier quoted context omitted.

No, they're not. The script they're critiquing uses #!/bin/bash, so they have to have been saying that #!/usr/bin/env bash is better.

They're definitely both critiquing the script in the OP for the same thing in the same way. They're in agreement with each other , not with the script in TFA

> They're in agreement with each other

Oh. Oh! This is a confusing thread. Apologies all!

Re: Techniques I use to create a great user experience for shell scripts

#244

Earlier quoted context omitted.

Sure, I'm not arguing that having a set of well defined outputs and passing objects around wouldn't be better. You're talking to someone that often laments that SmallTalk was not more popular. But you'd need to get the entire OSS community to land on a single object representation and then get them to independently change all the tools to start outputting the object version. PowerShell and Microsoft have the advantag…

Half way through your second paragraph I just knew you'd be reaching for 'jq'! All joking aside, that's not a bad solution to the underlying problem. Fundamentally, unstructured data in shell pipelines is much of the issue, and JSON can be used to provide that structure. I'm seeing more and more tools emit or accept JSON. If one can pinch their nose and ignore the performance overhead of repeatedly generating and par…

> Years ago, a project idea I was really interested for a while was to try to write a shell in Rust that works more like PowerShell.

Today's your lucky day!

https://www.nushell.sh

Re: Techniques I use to create a great user experience for shell scripts

#245
post #152
post #136

Earlier quoted context omitted.

As 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.

What is better?

Golang. 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).

Re: Techniques I use to create a great user experience for shell scripts

#246

Earlier quoted context omitted.

Yes. 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.

I don’t think it’s fair to compare a workflow that is designed for sed/awk. It’s about 10 lines of python to run my command and capture stdout/stderr - the benefit of which is that I can actually read it. What happens if you want to retry a line if it fails?

> I don’t think it’s fair to compare a workflow that is designed for sed/awk.

If your position is that we should not be writing bash but instead Python, then yes, it is absolutely fair.

> the benefit of which is that I can actually read it.

And you couldn't read the command pipeline I put together?

> What happens if you want to retry a line if it fails?

Put the thing you want to do in a function, execute it on a line, if the sub-shell returns a failure status, execute it again. It isn't like bash does not have if-statements or while-loops.

Re: Techniques I use to create a great user experience for shell scripts

#247
post #152
post #136

Earlier quoted context omitted.

As 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.

What is better?

Babashka/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

Re: Techniques I use to create a great user experience for shell scripts

#248
post #122

Earlier quoted context omitted.

I enjoy the simplicity of shell coding You mean, the complexity of shell coding? Any operation that in a regular language is like foo.method(arg) in shell expands into something like ${foo#/&$arg#%} or `tool1 \`tool2 "${foo}"\` bar | xargs -0 baz`.

> in a regular language [...] like foo.method(arg) Note what you just said: when you want an object with a method that takes a parameter, you find bash too complex. You gave an example that is not appropriate for bash. However, bash does have functions. So if you don't need an entire underlying object system just to run your logic, you could have function foomethod () { parm1=$1 #more logic }

My comment was more about basic string/number ops implemented as cryptic incantations, not functions per se. I regularly write bash. Simple things like trimming, deleting suffix, removing quotes, taking a substring, etc always look like someone is cursing in the code. I can’t remember this afterthought gibberish no matter how many times I write it, so I have to maintain few pages of bash snippets in my obtf.

Be damned the day I decided to write a set of scripts in it rather than looking for a way to make typescript my daily driver, like it is now. Bash “code” “base” is one of the worst programming jokes.

Re: Techniques I use to create a great user experience for shell scripts

#249
post #152
post #136

Earlier quoted context omitted.

As 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.

What is better?

Use bash for simple stuff, and Perl or TCL for applications.

Re: Techniques I use to create a great user experience for shell scripts

#250
post #234

Earlier quoted context omitted.

> 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.

> 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. A better system shell could make it easy to define shims for the existing programs. Also it could make their callin…

What you're suggesting is that the shell should have every possible command builtin and not call external programs.

Let's analyze your example with 'rm': it works as long as 'rm' is an internal routine. If it's an external program, independently of the syntax you use to specify the arguments, sooner or later the shell will need to actually call the 'rm' executable, and to pass '-rf' to it as argument number 1. The 'rm' executable will then examine its arguments, see that the first one begins with a hyphen and interpret it as an option.

As I said, the only way to avoid all this would be to replace 'rm' with an internal routine. Then you would replace 'cp' and 'ln', and what else? Of course 'echo' and 'printf', 'cat', 'ls', 'cd' maybe, why not 'find' and 'grep'? What about 'head', 'tail', 'cut'? Don't forget 'sed' and 'awk'... the list is getting longer and longer. Where do you draw the line?

Seriously, the only mitigation would be to define a function to 'sanitize' an argument to make it appear as a file if used as an argument to an external program. Something like:

  force_file() {
    case "$1" in
      -*) echo "./$1" ;;
      *)  echo "$1" ;;
    esac
}

This doesn't work with 'echo' though.

Post reply on HN