Explanation for newbies:

  • Shell is the programming language that you use when you open a terminal on linux or mac os. Well, actually “shell” is a family of languages with many different implementations (bash, dash, ash, zsh, ksh, fish, …)

  • Writing programs in shell (called “shell scripts”) is a harrowing experience because the language is optimized for interactive use at a terminal, not writing extensive applications

  • The two lines in the meme change the shell’s behavior to be slightly less headache-inducing for the programmer:

    • set -euo pipefail is the short form of the following three commands:
      • set -e: exit on the first command that fails, rather than plowing through ignoring all errors
      • set -u: treat references to undefined variables as errors
      • set -o pipefail: If a command piped into another command fails, treat that as an error
    • export LC_ALL=C tells other programs to not do weird things depending on locale. For example, it forces seq to output numbers with a period as the decimal separator, even on systems where coma is the default decimal separator (russian, dutch, etc.).
  • The title text references “posix”, which is a document that standardizes, among other things, what features a shell must have. Posix does not require a shell to implement pipefail, so if you want your script to run on as many different platforms as possible, then you cannot use that feature.

  • tetris11
    link
    fedilink
    arrow-up
    4
    arrow-down
    1
    ·
    edit-2
    8 hours ago

    My only issue is -u. How do you print help text if your required parameters are always filled. There’s no way to test for -z if the shell bails on the first line.

    Edit: though I guess you could initialise your vars with bad defaults, and test for those.

    • esa@discuss.tchncs.de
      link
      fedilink
      arrow-up
      8
      ·
      8 hours ago
      #!/bin/bash
      set -euo pipefail
      
      if [[ -z "${1:-}" ]]
      then
        echo "we need an argument!" >&2
        exit 1
      fi
      
      • rumba@lemmy.zip
        link
        fedilink
        English
        arrow-up
        2
        ·
        3 hours ago

        God I love bash. There’s always something to learn.

        my logical steps

        • #! yup
        • if sure!
        • [[ -z makes sense
        • ${1:-} WHAT IN SATANS UNDERPANTS… parameter expansion I think… reads docs … default value! shit that’s nice.

        it’s like buying a really simple generic car then getting excited because it actually has a spare and cupholders.

      • tetris11
        link
        fedilink
        arrow-up
        3
        ·
        edit-2
        8 hours ago

        That’s good, but if you like to name your arguments first before testing them, then it falls apart

        #!/bin/bash
        set -euo pipefail
        
        myarg=$1
        
        if [[ -z "${myarg}" ]]
        then
          echo "we need an argument!" >&2
          exit 1
        fi
        

        This fails. The solution is to do myarg=${1:-} and then test

        Edit: Oh, I just saw you did that initialisation in the if statement. Take your trophy and leave.

        • esa@discuss.tchncs.de
          link
          fedilink
          arrow-up
          2
          ·
          edit-2
          7 hours ago

          Yeah, another way to do it is

          #!/bin/bash
          set -euo pipefail
          
          if [[ $# -lt 1 ]]
          then
            echo "Usage: $0 argument1" >&2
            exit 1
          fi
          

          i.e. just count arguments. Related, fish has kind of the orthogonal situation here, where you can name arguments in a better way, but there’s no set -u

          function foo --argument-names bar
            ...
          end
          

          in the end my conclusion is that argument handling in shells is generally bad. Add in historic workarounds like if [ "x" = "x$1" ] and it’s clear shells have always been Shortcut City


          Side note: One point I have to award to Perl for using eq/lt/gt/etc for string comparisons and ==/</> for numeric comparisons. In shells it’s reversed for some reason? The absolute state of things when I can point to Perl as an example of something that did it better

          • tetris11
            link
            fedilink
            arrow-up
            2
            ·
            7 hours ago

            Perl is the original GOAT! It took a look at shell, realised it could do (slightly) better, and forged its own hacky path!

            • dx1@lemmy.world
              link
              fedilink
              arrow-up
              2
              ·
              edit-2
              6 hours ago

              I was about to say, half the things people write complex shell scripts for, I’ll just do in something like Perl, Ruby, Python, even node/TS, because they have actual type systems and readability. And library support. Always situation-dependent though.