[HN Gopher] The Case for Bash (2021)
       ___________________________________________________________________
        
       The Case for Bash (2021)
        
       Author : memalign
       Score  : 90 points
       Date   : 2023-05-18 08:09 UTC (14 hours ago)
        
 (HTM) web link (www.neversaw.us)
 (TXT) w3m dump (www.neversaw.us)
        
       | rfittich wrote:
       | I think this perspective is essential in our ever-evolving tech
       | industry. Bash, despite its quirks and often steep learning
       | curve, has its niche in our toolset.
       | 
       | Its power lies in its simplicity and direct access to system
       | level functions, which makes it an efficient tool for system
       | administrators and developers working in DevOps. It's excellent
       | for automating small to medium-sized tasks on UNIX-like systems
       | where the overhead of a full-fledged language would be overkill.
       | 
       | While it's true that bash has its limitations, the value of its
       | ubiquity cannot be overstated. The bash shell is everywhere -
       | from massive server clusters to tiny embedded systems. This means
       | that a bash script written on one system is very likely to work
       | unchanged on another.
        
         | csdvrx wrote:
         | > the value of its ubiquity cannot be overstated
         | 
         | TBH it's among the many reasons I've return to bash from zsh
         | 
         | I want to experience first hand the limitations I may hit on
         | other servers.
         | 
         | I also try to use #!/bin/ash in my scripts to live life in hard
         | mode :)
        
       | jagged-chisel wrote:
       | > It coordinates programs...
       | 
       | Sounds like a case for shells in general. No other script-
       | execution tools make running other programs (and linking their
       | inputs and outputs) so simple.
       | 
       | To overcome Bash's problems, one can choose another shell. But I
       | suppose you can't just pick your personal favorite and script in
       | its dialect, because then how would the human tasked with
       | integrating the script into $wherever know which shells to have
       | installed? You can stick with sh which is guaranteed to be
       | installed, or bash (indeed an improvement over sh) which is
       | nearly guaranteed to be installed.
        
         | mrspuratic wrote:
         | More than a decade ago I needed a multi-platform way to manage
         | Nagios client data collection (mostly) using whatever native
         | tools were available, so I wrote one. bash, gawk and send_nsca
         | were the only 3 binaries needed, and it ran well on 10
         | different *nixs (free and commercial) on Alpha, ARM, MIPS,
         | SPARC, X86 and X86_64 platforms.
         | 
         | Of course, after a decade of incremental tinkering I ended up
         | with exactly what you anecdon't want: ~2500 lines of shell
         | script and ~1000 lines of awk... LOC misleads of course, there
         | were 15 modular plugins, so there was a lot of boilerplate, and
         | this includes non-runtime ~1000 lines for install, self-test
         | and sanity checks.
        
         | JdeBP wrote:
         | Or one can learn the lessons that Debian learned over a decade
         | ago, and Ubuntu almost two decades ago, about bashisms,
         | maintainability, and performance; and script in at most the
         | Debian Almquist shell, whatever fancy shell one may be using
         | interactively.
         | 
         | * https://wiki.ubuntu.com/DashAsBinSh
         | 
         | * https://wiki.ubuntu.com/DashAsBinSh/Spec
         | 
         | *
         | https://wiki.debian.org/BootProcessSpeedup#Using_a_faster_sy...
         | 
         | * https://lists.debian.org/debian-
         | release/2007/07/msg00027.htm...
         | 
         | * https://lwn.net/Articles/343924/
         | 
         | * https://www.debian.org/doc/manuals/debian-
         | reference/ch12.en....
        
           | rascul wrote:
           | Interesting that efficiency is cited as the main reason in
           | several of those links. And here I see that dash starts up
           | only .001 seconds faster then bash. Maybe things were
           | different 15 years ago, I don't know.
           | 
           | The other concerns seem to have a very simple solution: use
           | bash in the shebang instead of sh if your script uses
           | bashisms.
        
             | JdeBP wrote:
             | That was one of the counterarguments to a common straw man
             | of the time. Changing the interpreter line was a valid
             | route. If you choose to use Bashisms, the counterargument
             | went, you just make that choice explicit; just as people
             | who used Korn/Z/whatever shell idiosyncrasies already had
             | to.
             | 
             | As for efficiency, recall that there were hundreds of
             | /bin/sh scripts in startup, administration, and everyday
             | operation of the system, from all of the /etc/rc.d/
             | (sub)scripts through things in cron and build systems and
             | package install/deinstall scripts to bunches of commands
             | that were /bin/sh scripts under the covers. So multiply
             | that difference by several orders of magnitude.
             | 
             | Amusingly, this is to a major extent still true. On these
             | operating systems systemd is nowadays parsing .INI files
             | over and over with its own custom .INI file parser, instead
             | of a chosen flavour of /bin/sh parsing shell scripts over
             | and over with whatever (Bison/YACC) parser they were using.
             | They haven't actually gone down the SunOS SMF (and s6)
             | route of compiling things into a machine-readable database.
             | And there are still lots of /bin/sh scripts elsewhere, as
             | service management is only one of several areas.
             | 
             | An interesting alternate history would have been if the Z
             | shell had been /bin/sh on Debian and Ubuntu instead of the
             | Bourne Again shell when this came up, and how much of a
             | difference employing zcompile everywhere would have made.
        
               | rascul wrote:
               | > As for efficiency, recall that there were hundreds of
               | /bin/sh scripts in startup, administration, and everyday
               | operation of the system, from all of the /etc/rc.d/
               | (sub)scripts through things in cron and build systems and
               | package install/deinstall scripts to bunches of commands
               | that were /bin/sh scripts under the covers. So multiply
               | that difference by several orders of magnitude.
               | 
               | And one of the links leads to a savings of 1 second on an
               | eeepc. Not very convincing.
               | 
               | https://wiki.debian.org/DebianEeePC/Dash
        
       | lloeki wrote:
       | > The Python and Ruby versions would be similar
       | 
       | Not Ruby!                 sh = Shell.cd('/')       sh.transact do
       | system('tail -fq /var/log/nginx/access.log') | system("awk
       | '{print $7}" | system("sort") | system("uniq -c") | system("sort
       | -rn")       end
       | 
       | Pretty sure one could get without the system method with Shell
       | having def method_missing(meth, * args) to call
       | system([meth.to_s, * args]) or something, turning it into:
       | sh.transact do         tail '-fq' '/var/log/nginx/access.log' |
       | awk '{print $7}' | sort | uniq '-c' | sort '-rn'       end
       | 
       | https://github.com/ruby/shell#pipe-etcprintcap-into-a-file
        
       | deafpolygon wrote:
       | Bash is a shell. Learn the shell, and you "learn" bash.
        
         | DonHopkins wrote:
         | At the risk of being accused of bash bashing, I'll throw down
         | that bash is a weak ineffective shell. A "shell" can and should
         | be so much more than all bash has to offer.
         | 
         | The much earlier more powerful ITS (Incompatible Timesharing
         | System) shell DDT (whose job name was HACTRN) had an integrated
         | PDP-10 machine language debugger / assembler / disassembler, so
         | you could interactively or batch "script" and patch DDT and
         | even other jobs in full blown PDP-10 assembly language.
         | 
         | Why invent yet another half assed "scripting" language that no
         | other jobs in the system are using, when you can use the same
         | fully powerful machine language that every job in the system is
         | using? And if you need to do anything complicated, there's
         | always LISP!
         | 
         | DDT's syntax was even more obscure than bash (and only a bit
         | less obscure than TECO), but it was much more powerful and
         | elegant, unleashing the full undiluted power of the PDP-10 at
         | your fingertips.
         | 
         | https://github.com/PDP-10/its/blob/master/doc/_info_/ddtord....
         | 
         | You could also write DDT commands in text files like your login
         | file, i.e. assembling a few lines of code to print the prompt
         | by making a system call to get the time and format it as text.
         | 
         | You could examine and deposit code and data, load and change
         | symbols, set breakpoints, in your own and even other user's
         | running jobs (processes)!
         | 
         | You could disconnect without logging out (accidentally or not)
         | and all your jobs would stay around until you logged back in,
         | at which time you could reattach your job tree and continue
         | what you were doing, all without running something like
         | "screen" -- that crucial feature was just built in and always
         | worked.
         | 
         | You could also pass ownership of jobs (like a running ZORK game
         | or LISP interpreter or FOOBAR feeper) back and forth between
         | users to share, like passing a joint. ;)
         | 
         | https://news.ycombinator.com/item?id=22840639
         | 
         | >It helped that ITS had no security whatsoever! But it had some
         | very obscure commands, like $$^R (literally: two escapes
         | followed by a control-R).
         | 
         | >There was an obscure symbol that went with it called "DPSTOK"
         | ("DePoSiT OK", presumably) that, if you set it to -1, allowed
         | you to type $$^R to mess with other people's jobs, dynamically
         | patch their code, etc. (The DDT top level shell had a built-in
         | assembler/debugger, and anyone could read anybody else's job's
         | memory, but you needed to use $$^R to enable writing).
         | 
         | http://www.poppyfields.net/filks/00117.html
         | 
         | The HACTRN                   Original song: The Raven
         | Original artist: Edgar Allan Poe         Filk author: Guy L.
         | Steele Jr.         Intro: Notes for those not familar with the
         | terms in this poem -- see below
         | 
         | [...]
         | 
         | DDT ("dee dee tee")
         | 
         | HACTRN ("hack-tran") = top level debugging and job controlling
         | procedure, capable of controlling up to eight simultaneous jobs
         | (which may themselves be DDTs!) and performing other
         | miscellaneous functions. HACTRN specifically denotes a DDT at
         | the top of a job tree, while DDT is the more general term. The
         | two terms refer to the same job in the poem, and are thus
         | treated as synonymous. Note that DDT requires its subjobs to
         | have unique names for obvious reasons; hence the concern over
         | seven jobs all named FOO.
        
           | hello_computer wrote:
           | Several of these sound like anti-features. Others are OS
           | issues and have no bearing on the shell (i.e. ownership hot-
           | swap). The ones that are useful have already been solved by
           | other programs (screen, gdb, et al). What is the advantage of
           | having it all packed inside the same executable?
        
           | deafpolygon wrote:
           | > And if you need to do anything complicated, there's always
           | LISP!
           | 
           | Are you an Emacser?
        
       | sigmonsays wrote:
       | it seems like most people that have dislike bash never spent the
       | time to learn it.
       | 
       | I have a love/hate relationship with is. I started with computers
       | in 2000 and wrote a ton of bash for various things. Compiling
       | software, running cicd, adhoc batch jobs, etc.
       | 
       | I've managed many cicd pipelines with bash in my time. While it's
       | not great, once you know the basics, you can be very successful.
       | That being said, rewriting the bash "program" in another language
       | is much advised. If your bash is over a few hundred lines,
       | chances are you've outgrown it
       | 
       | Some things in bash (mainly pipes and redirection) are just too
       | easy. Job control is also great. The 'process' and 'shell script'
       | are two primitives that make a lot possible.
       | 
       | Trying to do pipes or redirection in python is awful. There are a
       | ton of subtle bugs you have to worry about
        
         | bluepizza wrote:
         | Seems like you spent the time to learn it and still dislike it?
        
       | JdeBP wrote:
       | The article is a bit confused about whether it's making a case
       | for shell scripting in general, or for the Bourne Again shell in
       | particular. By the looks of things, its target readership is
       | people who don't use shell scripting, or interactive shells, _at
       | all_ ; so the former case would be more appropriate, and the
       | drawing of a distinction between the Bourne Again, Friendly
       | Interactive, Z, and other shells just muddies the waters for that
       | readership.
        
       | cwingrav wrote:
       | BASH is like Obi Wan. It isn't the most powerful or flashiest,
       | but it survived a long time, where others didn't, for very good
       | reasons. Bash runs basically everywhere. It has many modern
       | features you wouldn't expect. Its syntax is literally what you
       | would type on the command line if you were diagnosing or fixing
       | systems so you don't need to transpile to another language. Its
       | reliance on other programs means it is glue and can easily
       | incorporate highly cohesive functionality/tools others write and
       | maintain. Also, it's been around and is everywhere so you don't
       | worry about trying to incorporate the current latest and greatest
       | declarative tool (which will blow over in 5 years) into your
       | other workflows. Basically, don't disparage a Jedi/tool that has
       | survived where others didn't. There is a reason.
        
         | cwingrav wrote:
         | Also, use shellcheck. Incorporate it into you editor. Fix all
         | warning and don't ignore them. This will push you deep into
         | bash syntax rabbit holes but you come out better the other
         | side.
        
           | ndsipa_pomu wrote:
           | Also, familiarise yourself with
           | https://mywiki.wooledge.org/BashPitfalls
        
           | blueflow wrote:
           | Find the problem:                 echo "$(tr -dc A-Za-z0-9
           | </dev/urandom | dd count=1 bs=16 2>/dev/null)"            ^--
           | SC2005 (style): Useless echo? Instead of 'echo $(cmd)', just
           | use 'cmd'.
           | 
           | I have experienced so many situations where shellcheck is
           | giving harmful advice or warns me about the thing that is
           | exactly my intention.
        
             | rascul wrote:
             | I would probably do it this way:
             | 
             | tr -dc A-Za-z0-9 </dev/urandom | dd count=1 bs=16
             | 2>/dev/null; echo
             | 
             | A few less characters to type, you get your newline, and
             | shellcheck doesn't complain.
        
             | ndsipa_pomu wrote:
             | Using "echo" at all is a problem. It's recommended to
             | switch to "printf" instead as echo has unfixable problems,
             | especially with strings that start with a dash.
             | printf "%s\n" "$(tr -dc A-Za-z0-9 </dev/urandom | dd
             | count=1 bs=16 2>/dev/null)"
             | 
             | If you don't require the line feed, then you can just use:
             | tr -dc A-Za-z0-9 </dev/urandom | dd count=1 bs=16
             | 2>/dev/null
        
               | blueflow wrote:
               | The thing with echo is repeated again and again but not a
               | problem in the code i've just posted (due to A-Za-z0-9).
               | 
               | And i do require the line feed. Following shellcheck's
               | advice broke the code.
        
               | ndsipa_pomu wrote:
               | I'd also add that in the cases where you disagree with
               | shellcheck (it doesn't get everything correct all the
               | time), you can include a disabling comment just before
               | the line to tell shellcheck that you know best:
               | 
               | # shellcheck disable=SC2005
        
               | ndsipa_pomu wrote:
               | Not a problem until the random string starts with a dash
               | and you get unexpected results from "echo" interpreting
               | it as an option instead of an argument. Using "printf"
               | bypasses that issue as it's clear what the argument is.
               | 
               | Just tested it and ShellCheck is happy with the printf
               | version:                 printf "%s\n" "$(tr -dc
               | A-Za-z0-9 </dev/urandom | dd count=1 bs=16 2>/dev/null)"
               | 
               | It's also got a stylistic improvement (in my opinion,
               | anyhow) in that the line feed is explicit in the printf
               | command rather than being almost a side effect of echo.
               | 
               | Edit: I see your point about the "tr" not enabling a
               | dash, so my example falls a bit flat, but my point stands
               | in other scenarios. It's good practise to avoid echo
               | where feasible. I think the double quotes will also
               | protect in this instance. The problem with relying on the
               | tr string to not foul up echo is that you may later adapt
               | the code and use a different translate string which could
               | then introduce a tricky bug to track down.
        
               | [deleted]
        
             | xorcist wrote:
             | The style issue shellcheck reports here is probably what we
             | both suspect it is.
             | 
             | The call to echo has a likely purpose is to trim some
             | spaces from a string, but it's not at all obvious why this
             | is done or what the benefit is. In the best case, it leaves
             | the reader pondering this weird semi-no-op.
             | 
             | If you think shellcheck, and probably most readers, is
             | wrong in this assertion, just speak your mind and let's
             | learn from one another. But I certainly can't guess your
             | intention here.
        
             | saagarjha wrote:
             | ...what's the problem?
        
           | cwingrav wrote:
           | A lot of bash errors are not understanding possible cases due
           | to white space.. which shellcheck catches. After using it for
           | a while, I don't even really worry about white space because
           | of the good habits I've learned/(been forced to use).
        
             | ndsipa_pomu wrote:
             | That's all well and good until you come across a filename
             | with a linefeed in it - null termination is where it's at!
             | 
             | (I can't actually recall encountering a filename that
             | includes a linefeed)
        
               | Joker_vD wrote:
               | I've got several empty files on my desktop (on Windows)
               | serving as sticky notes of some sort, and they have line
               | breaks in their names, obviously.
        
               | ndsipa_pomu wrote:
               | I didn't even know that Windows supported that, but I try
               | to keep away from it as much as possible. Makes for an
               | interesting test of scripts, I suppose. Sometimes, I
               | script BASH to cope with any any filenames, but it
               | depends on the usage as a lot of the time you can
               | guarantee that files will be at least semi-sensible.
        
           | rascul wrote:
           | Also maybe check out the bash language server.
           | 
           | https://github.com/bash-lsp/bash-language-server/
        
         | ghostbrainalpha wrote:
         | So if Bash is like Obi Wan surviving where other didn't....
         | 
         | Is Bash just surviving because no one knows about it or has
         | remembers it while its been hiding in your system for 20 years?
        
           | paulddraper wrote:
           | Also, what will it be like as a Force ghost?
        
       | pjc50 wrote:
       | The only real advantage of bash (or other shells) is the ability
       | to build up to it from the command line; to use it as a REPL then
       | embed the stuff you've just done into a script.
       | 
       | The massive disadvantage of bash is that it uses a legal filename
       | character " " as a delimiter ("$IFS"). That means it's very easy
       | to write scripts which work fine on your test case but blow up in
       | a different context. And the worst case of that is accidentally
       | deleting the user's file system.
       | 
       | So many of the cute little bash examples you'll see, including I
       | think the awk one on this page, will go wrong if you have a space
       | in the wrong place in your filesystem. Or, god help you, a
       | newline. Or a file named "*". Or "--".
        
         | JdeBP wrote:
         | Or, put another way:
         | 
         | Getting the 10% of the cases that have whitespace or
         | metacharacters in variable values and filenames to work ...
         | takes the other 90% of the time. (-:
         | 
         | I habitually quote variable expansions, even when I _know_ that
         | the variables are never going to contain whitespace. Because
         | long experience has taught me that one day they will.
         | 
         | Just like I've learned never to assume that ${PATH} is always
         | non-blank and so assume that PATH="${PATH}:/something" won't
         | accidentally add the current directory to my search path. (-:
        
           | SAI_Peregrinus wrote:
           | /This name iss a valid POSIX /--file path
        
             | rascul wrote:
             | It might be nice to be more restrictive about what can be
             | in a filename. I'm sure there would be a lot of different
             | opinions though.
        
               | 9dev wrote:
               | Or, you know, it would be nice to have a shell that
               | didn't assume everyone lives in North America and speaks
               | only a single language..?
               | 
               | Lots of things written more recently have shown that
               | support for more, eh, inclusive, character encodings can
               | work just fine.
        
         | stcroixx wrote:
         | Hm, I write bash scripts routinely and never do it that way.
         | Always develop and run my scripts as files, starting with 'set
         | -x' if I need debug info. I keep interactive mode solely for
         | command line work, not development of scripts I plan to from
         | files.
        
         | wolletd wrote:
         | I guess the URL path in the Nginx log would be URL-encoded and
         | have a %20 instead of a space. And otherwise, it would actually
         | also a problem of that text based log format that uses spaces
         | as field delimiters itself.
         | 
         | Anyway: When I can "build up from the command line", then
         | apparently whatever I'm building up can be easily and
         | intuitively done in the command line. So, stuffing it into a
         | bash script is fast and easy and should be easy to understand
         | as well.
         | 
         | I just have real-world applications for small scripts that
         | aren't much bigger than those "cute little bash examples". When
         | you work with embedded systems, you do a lot of repeatable
         | stuff via SSH. I once ported an Installer to Python and now I
         | hate it because it has so much unhelpful noise between the
         | actual relevant commands being executed.
         | 
         | Yes, Bash has it's issues and requires some discipline, but so
         | do most other languages.
        
           | d0mine wrote:
           | > A lot of repeatable stuff via SSH
           | 
           | It looks like a use-case for fabric
           | https://docs.fabfile.org/en/stable/getting-
           | started.html#adde... It is the best of both worlds: shell
           | pipeline for one-liners, Python -- for complex logic.
           | 
           | Or if more declarative approach works in you case then
           | something like ansible could help https://docs.ansible.com/an
           | sible/latest/getting_started/inde...
        
         | hereonout2 wrote:
         | I spent my entire career avoiding file paths with spaces in.
         | 
         | On the very rare occasions I'm using an external dataset that
         | includes them I'll make a copy with renamed files using
         | underscores.
         | 
         | If more junior team members produce files with spaces in their
         | paths I quickly educate them in how problematic it can be.
         | 
         | It's pretty rare this is a problem for me or my team, perhaps
         | we're lucky in what we work on though.
         | 
         | Thankfully I have never seen a file named "*" or "--".
        
           | ndsipa_pomu wrote:
           | I too often avoid spaces in filenames, but when writing
           | scripts it's far better to ensure that you cope with them
           | properly. The trick is to always quote your variables by
           | default and then run shellcheck on your script so that it can
           | flag up the corner cases where quoting acts to unquote the
           | string. Of course, it'll also flag up a host of other
           | possible issues which are well worth fixing or at least
           | understanding why it's a possible issue.
           | 
           | Another common footgun is not including a double dash ('--')
           | at the end of command options so that the following filename
           | won't be interpreted as an option when it begins with a dash.
        
             | vram22 wrote:
             | >Another common footgun is not including a double dash
             | ('--') at the end of command options so that the following
             | filename won't be interpreted as an option when it begins
             | with a dash.
             | 
             | Yes. And if you have a file name that begins with a dash,
             | and you want to delete it, you can use this command:
             | 
             | $ rm -- -filename
             | 
             | where -filename is that file. Here, the -- (double dash)
             | means "end of the command-line options", so any argument
             | after that is treated as a non-option argument, in this
             | case, a filename for rm to delete.
             | 
             | This -- (double dash) works with many Unix commands. It was
             | introduced relatively early on in Unix history, after the
             | issue of filenames starting with a dash was found.
             | 
             | Although it is more likely that you would want to rename
             | the file, to remove the dash from the name.
        
             | throwaway858 wrote:
             | If you ever need to use GNU make (still a popular tool)
             | then you will be glad that you kept a policy of avoiding
             | spaces in file names.
             | 
             | There are places in Makefiles where no amount of quoting
             | will help you, and it simply cannot handle files with
             | spaces.
             | 
             | Yeah, this is a problem with the tool that should be fixed,
             | but my understanding is that it will never be fixed because
             | of architectural reasons. And it's a very popular, useful,
             | and most importantly, ubiquitous tool.
             | 
             | So this is another good reason to simply have a policy of
             | banning filenames with spaces (and there are many more
             | reasons).
        
           | munificent wrote:
           | Having to completely change the naming scheme you use for
           | human-authored and human-read artifacts entirely to route
           | around shitting, confusing escaping in a programming language
           | is not a convincing selling point for that language.
           | 
           | If you have a file whose contents are Shakespeare's "As You
           | Like It", you should be able to name that file "As You Like
           | It" without having to worry that the computer will vomit and
           | die on it. We deserve better tools.
        
         | Joker_vD wrote:
         | Quotes, dot-slash, quotes, double dash and quotes. Quotes,
         | quotes, shellcheck and quotes. Quotes, quotes, quotes, lovely
         | quotes!
         | 
         | Just don't write bugs, what's so hard about shell programming?
        
           | EuAndreh wrote:
           | Just shellcheck is enough.
        
             | ndsipa_pomu wrote:
             | Shellcheck won't catch the missing dashes ('--') at the end
             | of command options, so you could be in trouble if a
             | variable starts with a dash and the command interprets it
             | as an option rather than the filename. It's not
             | particularly obvious, but if people can upload a file and
             | specify its name, then they could compromise a script by
             | choosing a suitably evil name. If you get into a habit of
             | putting '--' at the end of the options and before the
             | filename variable, then you protect against that.
        
       | augustk wrote:
       | This article is not specifically about Bash, but about the shell
       | command language sh. The POSIX Shell is a standardized subset of
       | Bash which has even better portability. I would recommend
       | learning and using sh unless you really need Bash.
       | 
       | https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V...
       | 
       | Your script will use sh if it starts with #!/bin/sh (instead of
       | #!/bin/bash).
       | 
       | I can also recommend ShellCheck which is a shell script analysis
       | tool (implemented in Haskell) which can find errors and potential
       | problems in your scripts. On a Debian system, installing
       | ShellScheck is as simple as `sudo apt install shellcheck'.
        
         | ndsipa_pomu wrote:
         | I usually target BASHv3 in my scripts, but then I know the
         | environment that will be using those scripts. My biggest issue
         | with POSIX is the use of the backtick which is difficult to
         | read and parse.
         | 
         | ShellCheck is absolutely the most important thing to use when
         | writing scripts. Each time that you get a warning that you
         | don't recognise is a learning opportunity - just follow the
         | link provided in the warning. Also, take the time to add the "#
         | shellcheck disable=" comments so that scripts don't issue any
         | warnings from shellcheck.
         | 
         | I also recommend visiting https://mywiki.wooledge.org/BashFAQ
         | for avoiding the many footguns, especially with filename
         | parsing.
        
           | rascul wrote:
           | > My biggest issue with POSIX is the use of the backtick
           | which is difficult to read and parse.
           | 
           | POSIX also has $(command) for command substitution. It can
           | certainly be annoying when it's not used, though. I think
           | shellcheck will recommend it over backticks.
        
             | ndsipa_pomu wrote:
             | Thanks, I didn't know that, but then I almost never target
             | POSIX. My next complaint would be the use of '[' as a test
             | rather than my preferred '[['.
             | 
             | Edit: After looking for a problem with POSIX, I found this
             | obscure issue that may well catch out people as under
             | POSIX, IFS is a terminator rather than a separator:
             | https://mywiki.wooledge.org/BashPitfalls#IFS.3D.2C_read_-
             | ra_...
        
           | augustk wrote:
           | > My biggest issue with POSIX is the use of the backtick
           | which is difficult to read and parse.
           | 
           | I always use $(...) or rather "$(...)" instead of backticks.
           | Command substitution shall occur when the command is enclosed
           | as follows:              $(command)            or (backquoted
           | version):              `command`
           | 
           | https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V.
           | ..
        
         | dspillett wrote:
         | _> The POSIX Shell is a standardized subset of Bash which has
         | even better portability._
         | 
         | It would be much more correct to say that bash's features are a
         | superset of the shell features standardised by the POSIX
         | standard, as is the case for several other shells (each adding
         | their own parts on top of the standard) too.
        
         | everybodyknows wrote:
         | > This article is not specifically about Bash, but about the
         | shell command language sh.
         | 
         | Exactly. The title is just plain _wrong_. Furthermore, TFA does
         | not argue a  "case", it simply tries to specify the language.
        
         | VWWHFSfQ wrote:
         | > I would recommend learning and using sh unless you really
         | need Bash.
         | 
         | Nah I like using bash features and all the systems that I care
         | about have /bin/bash so it doesn't matter.
        
         | spyremeown wrote:
         | >I would recommend learning and using sh unless you really need
         | Bash.
         | 
         | I don't buy this argument. Ok, it's a standard, but sometimes
         | it's a pain-in-the-hole standard. Bash augmentations lessen
         | some of the pains, and it's just nicer. The only situation is
         | if you're using busybox in a very limited system or you
         | reeeeeally need your script to run on many difference unices,
         | which let's be honest, is not that common nowadays.
        
           | kaba0 wrote:
           | > Bash augmentations lessen some of the pains, and it's just
           | nicer
           | 
           | Both sh and bash are terrible, ugly hacks. Anything that
           | requires more than 3 lines of them (including the #! line)
           | should be written in a proper scripting language.
           | 
           | Though I do agree that cross-platformity to that level is
           | rarely meaningful, and so things like python are just as
           | likely available/can be made available.
        
             | wvh wrote:
             | My system Python tree is almost 1GB. That doesn't matter
             | for desktop systems, but most software is published as
             | container images these days and using a language like
             | Python, Ruby or Perl for an image that doesn't already need
             | it is pretty wasteful and pulls in a lot of extra
             | dependencies.
             | 
             | I'm not sure there is a good alternative to sh/bash shell
             | scripts as most dynamic languages have become pretty large
             | dependencies these days.
        
               | kaba0 wrote:
               | That surely includes plenty of globally installed
               | dependencies. I looked at the package sizes for debian
               | and it is around 100 kB for the python3 package and on
               | the order of another 100kb for python3-minimal. Couldn't
               | find a cumulative install size, but it is surely not
               | larger than a few megabytes.
        
               | CamJN wrote:
               | Just span up a clean alpine linux container and installed
               | python3, it added 51MB according to apk.
        
             | sgarland wrote:
             | Until someone decides to write something that's only
             | available in X version of Python. While there are certainly
             | v4 and v5 bash-isms, they are far and few between compared
             | to most languages.
             | 
             | ...that said, having to support bash 3.2 for MacOS is a
             | horrible thing.
        
             | ndsipa_pomu wrote:
             | Which version of python though?
        
               | kaba0 wrote:
               | Add a flake.nix file and you get completely reproducible
               | program versions if you really want.
               | 
               | But I know that you meant it as a rhetoric, so my non-
               | rhetorical answer would be that python3 is almost
               | universally available on distros that are not minified
               | deliberately (containers).
        
               | ndsipa_pomu wrote:
               | > python3 is almost universally available on distros that
               | are not minified deliberately (containers)
               | 
               | Writing control scripts for use inside containers is
               | currently my biggest application of BASH scripts. What
               | makes BASH (or other shells) handy is the lack of
               | supporting files that are needed - just copy in the
               | script and you're ready to go.
        
               | time0ut wrote:
               | I was going to say something similar. I try to avoid
               | adding anything to my final images. Each extra dependency
               | is something else to update, more surface areas for
               | attacks, another thing to justify, etc. Much rather just
               | use the slimmest base and the tools already available.
        
               | paulddraper wrote:
               | 3
               | 
               | Which version of Bash?
        
               | Izkata wrote:
               | The various sub-versions of bash are a lot more
               | compatible than the sub-versions of python 3. Just today
               | stuff was breaking on me because of differences between
               | python 3.6 and 3.8
        
           | synergy20 wrote:
           | I do small embedded systems with busybox, even that I can
           | squeeze in bash when I need that, it's about 1MB in size and
           | gives a lot more than busybox's sh. Another option is Lua
           | which is also great.
        
           | blueflow wrote:
           | > is not that common nowadays
           | 
           | Due to docker, minimalistic Linux'es have been more common,
           | including trimmed-down versions of distros that would
           | otherwise feature bash.
        
             | synergy20 wrote:
             | bash is rarely the focus though, it really just costs 1MB
             | in storage, which is nothing comparing to python,etc.
        
               | 9dev wrote:
               | Well, usually I have to decide between ,,do I look up the
               | magic incantation to install bash in this container and
               | risk fucking up the layer cache" or ,,do I modify this
               | script to not use bash-isms and feel like I'm a Unix
               | purist in the process", and the answer is the latter
               | usually
        
               | paulddraper wrote:
               | Nonetheless Bash is very frequently omitted in my
               | experience.
        
           | JdeBP wrote:
           | All of this was covered in great detail in the 2000s, when
           | Debian and Ubuntu switched /bin/sh to the Debian Almquist
           | shell, which was basically POSIX-only with some 3 things that
           | Debian people simply couldn't live without, and encouraged
           | system scripts to use it. If you weren't around then, go and
           | read the discussions. They're mostly still available, and
           | they cover some important stuff that straw man
           | counterarguments regularly miss.
           | 
           | The Debian people were concerned, for starters, with how much
           | time the Bourne Again shell spent, at process initialization,
           | setting up things for extensions and interactive features
           | that were never employed in non-interactive "sh" mode; a
           | significant cause for concern given how much of the system
           | was executable shell scripts.
        
             | jmclnx wrote:
             | >with some 3 things that Debian people simply couldn't live
             | without
             | 
             | Curious, what are the 3 things ?
             | 
             | But yes, people should always use sh (or ksh) for scripting
             | as opposed to bash, why, it is far more portable to other
             | systems.
        
               | JdeBP wrote:
               | Originally it was echo -n, local, and logical operators
               | in test. There was just so much Debian stuff that assumed
               | these.
               | 
               | * https://bugs.debian.org/cgi-
               | bin/bugreport.cgi?bug=294962
               | 
               | They've added 2 more since.
               | 
               | * https://www.debian.org/doc/debian-policy/ch-
               | files.html#scrip...
               | 
               | Strictly speaking, there are other differences between
               | the Debian Almquist shell and a truly SUS conformant sh.
               | 
               | * https://unix.stackexchange.com/q/697007/5132
               | 
               | But the aforementioned are what Debian people explicitly
               | wanted and couldn't live without. Note that the
               | StackExchange answer is a comparison of a 2022 dash to a
               | 2017 standard, neither of which existed at the time.
               | Debian Policy, the Debian Almquist shell, and the POSIX
               | standard have all been revised since then.
        
         | latexr wrote:
         | macOS and plenty of popular Linux distributions symlink /bin/sh
         | to /bin/bash. Some link it to /bin/dash. There may be different
         | ones.
         | 
         | Meaning /bin/sh is _not_ more portable because you can't be
         | sure which shell will be used.
        
           | jsyolo wrote:
           | Bash is POSiX compatible.
        
           | augustk wrote:
           | ShellCheck can check for POSIX compliance with the option
           | `--shell sh', e.g.                 shellcheck --shell sh
           | myscript.sh
        
           | VWWHFSfQ wrote:
           | Not only is it not more portable, POSIX doesn't even require
           | that it exists at all.                   Applications should
           | note that the standard PATH to the shell cannot be assumed to
           | be either /bin/sh or /usr/bin/sh, and should be determined by
           | interrogation of the PATH returned by getconf PATH, ensuring
           | that the returned pathname is an absolute pathname and not a
           | shell built-in.
           | 
           | I don't know how this trend started but now it's been cargo-
           | culted to death. Same with the /usr/bin/env thing in
           | shebangs.
        
             | shawabawa3 wrote:
             | One use-case for /bin/sh over /bin/bash these days is that
             | the alpine docker image (base image for a lot of docker
             | images) has /bin/sh but not /bin/bash
        
         | rascul wrote:
         | I recommend learning bash if you know that bash is available
         | for all your targets, since bash brings many niceties that sh
         | doesn't have.
        
           | justaj wrote:
           | Some may have different Bash versions installed though.
        
             | rascul wrote:
             | That's easy to check for. sh implementations can vary also.
        
               | justaj wrote:
               | Does the POSIX implementation vary for sh though? AFAIK
               | some interpreters choose to add some extras (like
               | `local`), but all of them at the very minimum must adhere
               | to the POSIX spec from what I've understood.
        
               | rascul wrote:
               | There are a couple examples in this stack overflow
               | answer:
               | 
               | https://stackoverflow.com/questions/11376975/is-there-a-
               | mini...
        
         | myhf wrote:
         | > not specifically about Bash, but about the shell command
         | language sh
         | 
         | or as I've taken to calling it, Ba + sh
        
       | shmerl wrote:
       | Good points. But I wish Bash had better syntax and built in
       | support for basic concepts like boolean logic. Try to compose
       | some complex boolean expression in Bash and you will quickly hit
       | problems.
        
       | DonHopkins wrote:
       | The only thing you need Bash for is to install Python.
        
       | BirAdam wrote:
       | I've written a ridiculous number of shell scripts to automate
       | many many things. It's great for doing something now, and it's
       | great as a way to interact with a machine. It is not great in all
       | cases. Particularly: array handling is bad, it's slow if you
       | start using actual Bashisms, very few younger devs seem to know
       | it.
       | 
       | The shell is great cuz it's there and it can cover about 50% of
       | use cases for server side automation, but it's bad for the
       | reasons mentioned above.
       | 
       | I love it and I hate it.
        
       | 666satanhimself wrote:
       | [dead]
        
       | badrabbit wrote:
       | I feel like zsh is for pros maybe. I use Linux daily and write
       | python and shellscripts. Zsh has been defaulted all over the
       | place but all that meant for me is I have to figure out how to
       | get it to do things the bash way once in a while.
       | 
       | I see no reason why distros like ubuntu or kali would default to
       | zsh.I use the shell for sysadmin stuff, anything complex or app
       | specific gets at least a python treatment.
       | 
       | The whole thing reminds me of python 2->3 or sysv init to
       | systemd. There must be people somewhere deeply invested in these
       | changes and their voice is certainly much more valuable than the
       | average opensource joe user. Defaults matter and the time I and
       | millions had to spend learning to transition for no direct
       | benefit to us has value. The whole distro model of everyone
       | getting a distro they like falls apart when not enough people can
       | fork.
       | 
       | Overall, this devalues opensource as an investment. Because of
       | unpredictable hidden costs like this.
        
       | todd8 wrote:
       | I'm a computer scientist/software engineer that has used
       | primarily Unix or Linux systems since the 80's. I write shell
       | scripts occasionally, but I just find them error prone enough
       | that I'd rather use python than sh for complex scripts. Python
       | has some packages that make working with files, directories, and
       | processes tolerable and at least I can understand the string
       | quoting rules in python.
       | 
       | Generally my order of preference for shell scripting tasks is:
       | python > bash > pearl > tcl > sh > anything > AppleTalk.
        
       | faeriechangling wrote:
       | The thing that makes me loathe Bash more than anything else is
       | it's 3 types are string, int, and list and those are not the only
       | types of data I work with day to day.
        
       | majkinetor wrote:
       | Quality of the articles on the front page seems to be rapidly
       | declining...
        
         | Gualdrapo wrote:
         | Font alone is so thin is unreadable. It's funny to say that in
         | HN where fonts are so small too.
        
       | msoad wrote:
       | I ask chatgpt for bash scripts. So useful and every time I'm
       | learning something new
        
         | BoxOfRain wrote:
         | ChatGPT is great for quickly getting the bones of a script but
         | you still need to know bash reasonably well, ChatGPT will
         | sometimes merrily write stuff that looks correct but is
         | actually a foot-gun and that's not great when things like `rm`
         | are involved.
        
           | msoad wrote:
           | I know enough bash to be able to spot those things. but I
           | might forget how exactly `awk` should be used to split a
           | string or such. So asking ChatGPT is a quick way of getting
           | those things working...
        
             | Danjoe4 wrote:
             | ChatGPT excels at regex, awk, grep, etc.
        
       | SPBS wrote:
       | So it's both ubiquitous and a terse DSL for managing and
       | coordinating programs. Yeah I agree. Also if you're on Windows
       | it's nice that PowerShell is always preinstalled and serves the
       | same purpose.
        
       | vram22 wrote:
       | IMHO, the best resource to learn about both Unix shell usage at
       | the command-line prompt, and shell programming in .sh script
       | files, is still the book "The Unix Programming Environment" by
       | Kernighan and Pike, except for shell gotchas and subtleties which
       | were discovered later.
       | 
       | Of course, they still would not have covered all possible issues
       | known even at that time, because that was not the focus of the
       | book, which was to be a Unix tutorial, not just on shell, but
       | many other commands, general Unix usage, and the environment too
       | (hence the title of the book).
       | 
       | But they did cover and warn about some issues, including giving
       | solutions.
        
       | stanleydrew wrote:
       | This argument isn't very compelling. Shell scripts are great at
       | tricking you into believing you've got something 100% working
       | when in fact you've only accounted for the happy path and maybe
       | two or three failure cases. This is the primary reason shell
       | scripts are so often broken. There are tons of assumptions baked
       | in which are easily violated.
       | 
       | If your shell script keeps breaking, and you keep fixing it by
       | writing more shell, then you're in an abusive relationship with
       | your programming environment.
        
       | pgtan wrote:
       | Well, Kornshell (ksh93) has some nice programming features, much
       | better than bash.
        
       | jquast wrote:
       | We should have better local shells that "drive" remote sh/bash
       | shells through transpilation, so that we can have modern shells
       | anywhere without concern for remote install, access to install or
       | compile, compatibility, carrying customizations, etc.
        
       | BoardsOfCanada wrote:
       | Maybe this already exists, but I imagine if someone wrote at
       | library for interacting with gnu or posix commands from python
       | (or ruby, or...) that built up the commands in a structured way
       | and parsed the replies and put them in a dict, that would be very
       | nice to use instead of bash-scripts. Every weird thing that you
       | wanted to do would be a lot easier to do in python than in bash,
       | and none of that looking out for spaces in strings and so on.
        
         | throwaway858 wrote:
         | There is this for Haskell, which automatically converts all
         | shell commands (like "ls") to regular Haskell functions:
         | 
         | https://chrisdone.com/posts/shell-conduit/
         | 
         | It uses a Haskell streaming library so you can do stuff like
         | shell pipelines and file redirection (but in a more structured,
         | safer and more powerful way)
        
         | meta-meta wrote:
         | https://github.com/babashka/babashka comes to mind
        
       | frumiousirc wrote:
       | Am I missing something or is the article's central example using
       | `tail` fundamentally broken?
       | 
       | The `sort` blocks until input is closed yet `tail -f` never
       | closes its output.
        
         | [deleted]
        
         | JdeBP wrote:
         | You'll be pointing out that [ is a built-in command, next. (-:
        
           | rascul wrote:
           | It's also a binary in /bin (or a symlink because of /usr
           | merge) and it's silly that the article tries to view [ in a
           | pager.
        
       | SomeCallMeTim wrote:
       | Bash/Sh is an objectively awful programming language. You could
       | likely fill an entire book with all of the design fails that is
       | Bash script syntax. Only in a shell script would you ever need
       | eight backslash characters in a row in order to accomplish
       | something...and "space as delimiter" is awful in _so many ways_.
       | 
       | But especially Sh runs everywhere, so it's good to know. This
       | seems to be the article's point.
       | 
       | Honestly, though? The right answer is to transpile a better
       | language to Sh.
       | 
       | Looking around, there have been several half-hearted, abandoned
       | attempts. But apparently everyone is happy to just fall back on
       | the "accidental syntax" of Bash that really doesn't make sense
       | when compared to ... any other language.
       | 
       | I put up with Bash because there's no better alternative. That
       | doesn't mean we _should_ put up with Bash; just that we _must_
       | put up with it at least to the point where it can run code
       | written in a _real_ language.
        
         | sgarland wrote:
         | Shell is an objectively _difficult_ programming language. But
         | difficult != awful. Pointy and ready to bite you if you make a
         | tiny mistake? Yes. Ubiquitous and not going anywhere? Also yes.
         | 
         | But given that *nix tooling output defaults to text, it's hard
         | to argue against a universal language that talks to all of it.
        
         | danielvaughn wrote:
         | I'm not very knowledgeable in this area as I don't do much
         | shell scripting, but isn't zsh supposed to be some kind of
         | enhancement over bash? Does it suffer from the same issues?
         | 
         | Regardless, the idea of a language that transpiles to bash is
         | kinda interesting.
        
         | marcosdumay wrote:
         | > "space as delimiter" is awful in so many ways
         | 
         | Yes. But it's also absolutely great in so many ways.
        
       ___________________________________________________________________
       (page generated 2023-05-18 23:01 UTC)