💾 Archived View for siiky.srht.site › programming › shell.gmi captured on 2024-05-12 at 15:14:23. Gemini links have been rewritten to link to archived content

View Raw

More Information

⬅️ Previous capture (2023-03-20)

-=-=-=-=-=-=-

RE: Misadventures with bash shell

siiky

2022/08/01

2022/08/02

en

As StackSmith prompted:

In the meantime, if you have a few minutes, write about why you love your shell. I really want to know.

Misadventures with bash shell

I don't love it, I even agree with some of the points raised, but after learning it one has to admit: most tasks are damn terse. And I can't imagine any Lisp-like syntax that could come even close -- BTW it's been tried at least once, that I know of:

Scsh

Scsh (Wikipedia)

Maybe interesting, maybe not, but here are some of the features I use most often. I never know what's the right if/then syntax either, so when I want this:

(when (file-exists? "...")
  (do-this)
  (and-that))

(unless (file-exists? "...")
  (do-this)
  (and-that))

I write this instead:

[ -f "..." ] && (do-this; do-that)

[ -f "..." ] || (do-this; do-that)

No more guessing where the hell the bang should go.

Loops all follow the same pattern:

for/while/until ...; do ...; done

You can put the body of the loop in the background too, but obviously be careful not to forkbomb yourself.

for/while/until ...; do ... & done

Something I do often to start multiple terminals in the same Nix shell:

exec nix-shell --run 'sh -c "for i in {1..4}; do terminal & done"' &

The `exec ... &` makes the nix-shell and child processes "independent", so that I can continue to use the current terminal and/or close it without affecting the others. `for i in {1..4}` is equivalent to `for i in 1 2 3 4`. I think this syntax is relatively "new"; if you don't have it, you can use seq instead:

for i in `seq 1 4`; do ...; done

Doing something for each line of input:

some-command | while read line; do ...; done

read alone is a can of worms. It's very useful for simple things so worth knowing.

And some of the most important stuff: strings! There are 3 "types": single quote, double quote, and backtick (plus $(...)). If you're unsure what type of string you need, go with single quotes because they're the safest and least surprising. If you need to interpolate values into your string, use double quote strings. If you need the result of a command as a string, use backticks (like the seq above). Backticks can be embedded in other string types.

test=hello
echo 'hello world'         # "hello world"
echo '$test world'         # "$test world"
echo "$test world"         # "hello world"
echo `echo "$test world"`  # "hello world"
echo $(echo "$test world") # "hello world"

(I got some examples wrong as I was writing this haha)

In extreme cases, even though it's a mess to read, you can take advantage of automatic string concatenation to mix string types.

echo 'a string with a single quote ('"'"')'
echo "a string with a double quote ("'"'")"

I've tried escaping in the past and failed too many times. This has never failed me once.

As a sort of conclusion: for some reason bash is one of the most, if not the most, popular interactive shell. Probably because it's the default in many Linux distros, especially the biggest ones. The default effect certainly worked with me because I'm still "stuck" with it. But bash isn't the only one out there, so if you don't like it, do yourself a favor and try a different one! Some shells I can think of: fish, zsh, ksh, ion (of RedoxOS), csh.

As for me, I've read my share of shit-throwing at bash, but it's been working OK. I don't need the fancy features offered by fish or zsh. If I tried any new interactive shell, it'd probably by zsh or ion.