5 ms·
> I may never write a bash script again I wrote 2x 200 line-ish shell scripts recently, and it was simply terrible, and although I'm increasingly convinced we
by mustache_kimono 4y ago
> I may never write a bash script again
I wrote 2x 200 line-ish shell scripts recently, and it was simply terrible, and although I'm increasingly convinced we need a shell like abstraction, I can't believe `bash` is the best we can do. Really hope I find one of these alt shells that suits me. Not a fan of Python but xonsh looks really cool too.
- pletnes 4y agoXonsh is very posix/bash-like but you can call python functions in an integrated way. Even if you don’t love python it’s a more sane language than bash. I really like it but I’ve been using zsh for too long.
- nerdponx 4y agoBash is not the best we can do! If you want a traditional Unix-like shell that is mostly sensible in the places where Bash is not, check out Zsh. It has a ton of complicated features, but most Bash scripts can be ported easily (if not outright copied and pasted). Zsh has fewer footguns by default than Bash, and it has more "safety" settings that you can enable. There is also the Oil shell, whose creator often posts on HN, and which I think is meant to be a superset of Bash, but I have not used it myself and can't vouch for it. As for the alt shells, I've was specifically interested in Elvish, but I dropped it as soon as I saw that they don't support parameter interpolation in string literals, like `"${HOME}/.local"`. This is such a common operation in shell scripts that I have no interest in a shell that doesn't support it, and I can't imagine why Elvish doesn't.
- nerdponx 4y agoSince I can't edit my post anymore, here are some additional thoughts: Traditional shell scripting languages are great at exactly three things: typing commands interactively, running other programs, and sourcing other shell scripts. They are also is distinct in that they are "stringly-typed" (i.e. everything is a string), and moreover that syntactically bare symbols are also strings. Typing commands interactively is essential because... it's a shell. That's what it's for. Most programming languages do not and should not optimize for this. But it's literally the purpose of a shell, so a shell should be good at it. "Running other programs" includes invoking them (literally 0 extra syntax), piping them (one letter: |), and redirecting the standard input and output streams to files (>, <, <<, etc.). This is one of the great innovations of Unix and nothing holds a candle to its elegance and convenience, even if sometimes we get frustrated that pipes are "dumb" streams of bytes and not something more structured. "Sourcing other shell scripts" practically isn't much different from "running another shell process", except that source'd shell scripts can set shell parameters and environment variables, which is an important part of e.g. the X11 startup system: the global /etc/X11/Xsession script sources the user's ~/.xsession script, so any environment variables set in the latter are propagated to the former, and thereby are inherited by the X11 window manager when it eventually starts. If you wrote the /etc/X11/Xsession script in any other programming language, you'd have to inspect the environment variables of the ~/.xsession process and "merge" those values back into the current process' environment. On being stringly-typed, I think it's mostly good in the context of the "two things that it's good at" described above. It cuts down on syntactical noise (otherwise "everything" "would" "always" "be" "quoted" "everywhere"), makes string interpolation painless, and generally supports the "typing commands interactively" use case. Make and Tcl are the only other popular languages in this category. Perl and Ruby allow it in specially-delineated areas of code. Moreover, Bash, Ksh, and Zsh all have arrays, which helps fix some of the biggest problems of everything being a string. In short, if your program can make good use of the above features, then a traditional shell is a great choice. If you program does not need those features, do not write your program using a shell script, because shell languages are awkward at best in pretty much all areas. And if you are considering an "alt" or "neo" shell language, in my opinion it must excel in the above two categories. Being stringly-typed is a matter of taste, but the language should also probably support bare-symbols-as-strings and string interpolation. Python, for example, is not a good shell scripting language because it is not easy to type nontrivial commands interactively, it lacks tidy syntax for input/output redirection (even though it's actually pretty easy using the standard library), and it lacks bare-symbols-as-strings. So instead of: #!/bin/sh foo -x 1 -y 2 "$ABC" | bar --json - you have to write something like: #!/usr/bin/env python3 import os from subprocess import Popen, PIPE, run foo_cmd = ['foo', '-x', '1', '-y', '2', os.environ['ABC']] bar_cmd = ['bar', '--json', '-'] with Popen(foo_cmd, stdout=PIPE) as foo_proc: foo_proc.stdin.close() run(bar_cmd, stdin=foo_proc.stdout) You can of course write your own library that abstracts this and uses symbols like > >> < << | to mimic what a shell does. Maybe that's what Xonsh is, I haven't looked at it myself. But this hopefully demonstrates why the base language Python is not a good shell, despite it being portable, being nearly ubiquitous nowadays, being relatively easy to use and learn, being "safe" in many ways that traditional shell languages are not, and having a huge and useful standard library.
- AtlasBarfed 4y agoI would also like to add for a better shell: Please add another standard output stream. stdout is for output stderr is for error messages stdlog for status/tracking, verbose output, event streams. Too often this gets shunted to stderr, and I don't want to logfile hunt. Other examples: download status from curl, verbose output flags in things like ssh and other comm programs that need configuration debugging on the regular, and others. Nushell seems to also focus on json output for commands. I think this should be a requirement pushed into all unix commands that do output (LS! please please please a json output flag for simple ls which CANNOT BE PARSED RELIABLY).
- nextaccountic 4y agoI would recommend Oil! http://www.oilshell.org/release/latest/doc/idioms.html http://www.oilshell.org/release/latest/doc/idioms.html It removes the need to quote every variable, and this is fantastic
- nerdponx 4y agoFWIW this is also the main selling point of Zsh. I should go through this document in detail (thank you for linking it!) but a quick search shows that Zsh is not mentioned even once, and I think a Zsh comparison would be really valuable for people like me. Or is it like Neovim vs. Emacs at that point, where neither one is "better" and it's just a matter of taste and/or whichever one you happened to try first?
- nextaccountic 4y agoWell I actually use zsh (I always mean to switch to oil though), and.. in zsh, you don't need to quote variables? Are you sure? Oh.. I just tested here. It works! $ mkdir -p /q/a\ b/x $ a="a b" $ ls /q/$a x And in bash: $ a="a b" $ ls /q/$a ls: cannot access '/q/a': No such file or directory ls: cannot access 'b': No such file or directory The weird thing is, my shell is zsh but my shell scrip ts are all either #!/bin/bash or straight #!/bin/sh, so I never took advantage of this Anyway, I want to link also to http://www.oilshell.org/release/latest/doc/upgrade-breakage.html http://www.oilshell.org/release/latest/doc/upgrade-breakage.... http://www.oilshell.org/release/latest/doc/warts.html http://www.oilshell.org/release/latest/doc/warts.html http://www.oilshell.org/release/latest/doc/known-differences.html http://www.oilshell.org/release/latest/doc/known-differences... <- here it talks about zsh a bit
- nerdponx 4y agoThe only thing to keep in mind about Zsh parameter expansion is that unquoted empty values will be dropped entirely, while quoted empty values will be treated like the empty string '': show_nargs() { print $# } q= show_nargs $q # 0 show_nargs "$q" # 1 So it doesn't completely solve the need for defensive quoting, but at least it mitigates the need for the most part.
- anthk 4y ago>If you want a traditional Unix-like shell that is mostly sensible in the places where Bash is not, check out PERL. Sh, awk, sed and mini-C all at once.
- nerdponx 4y agoI tried to like Perl. I really really did. `while (<>)` and regex literals are amazing. Everything else is kind of rough for me, especially the way arrays and hash tables work, and I much prefer Zsh, AWK, or Python for the same niche.
- fuzzygroup 4y agoI find the lack of string interpolation to be the one thing that kills me about javascript. The lack of it feels wrong and I can't get behind languages that don't have easy interpolation. Yes Ruby has ruined me.
- AprilArcus 4y ago`template${Math.random() > 0.5 ? 'strings' : 'literals'} have beern part of the language since 2015!`
- jackac 4y agoElvish: $E:HOME'/.local'
- naikrovek 4y agoBash is not the best we can do, but it is definitely the best that most people agree on. I fear there will be no defacto bash replacement for many years.
- exyi 4y agoWhat do you mean by "agree on"? We never agreed the programming language, which means ... that I can choose whatever I like.
- naikrovek 4y agowhat's the default/defacto scripting language on all unix or unix-like operating systems? Bash. (except MacOS I guess) why? because it is the best thing that everyone can agree on as being the stock shell that should always be installed by default. until we collectively agree on a replacement, bash will remain, along with all of its problems and everyone will write for it because it's the standard shell that's always installed. many much better shells exist. we can't agree on what should supplant bash, and so it remains. everywhere.