1. 11
  1.  

  2. 5

    I can’t take any article on bash programming seriously when it uses unquoted variables, especially one about defensive coding.

    1. 3

      Defensive bash programming is good and important, but this article will not help you do it. Rather, this article is full of advice that is so bad that I suspect that it was written as a satire about bad programming advice.

      The very first line of code in the article has a bug due to not being sufficiently defensive:

      readonly PROGNAME=$(basename $0)
      

      Oh yeah, that’s gonna work real fucking well when $0 is “/home/kragen/buggy software/kfirlavi/rebuild”. This kind of stupid bug is everywhere in this article.

          local files=$@
          local i
          for i in $files
      

      Great, let’s call our filename “i” so that people will think it’s an integer once the loop is more than ten lines long. And hope that they don’t confuse “$i” with “$1”. And also introduce a completely unnecessary bug in handling filenames with spaces; for filename in "$@" would have been clearer, shorter, and most importantly, correct.

      Also, as apenwarr writes, “Assigning $@ to a variable is unspecified and it doesn’t do anything consistent.”

      main()
      • Intuitive for functional programming

      This shows that the author doesn’t know what “functional programming” means. Or, arguably, “intuitive”.

      is_not_empty() {
         local var=$1
      
         [[ -n $var ]]
      

      }

      Great, so if is_not_empty errors.log; then echo see errors.log >&2; fi will always print an error message! Whereas if you use [[ -n errors.log ]] then the bug is obvious if you know ksh or bash already.

      Here’s what I recommend for defensive bash:

      • never let bash autosplit your variable expansions; use doublequotes for that.
      • If you need aggregate data structures, consider using argument lists, multi-line files (possibly via a pipe), or using a different programming language, or using bash arrays. Not variables containing space-separated words.
      • always -print0 and -0 for find and xargs. Newlines in filenames are uncommon, but xargs splits on spaces too by default!
      • set -e at the beginning, always. You can use ||: if need be to ignore failures silently. (apenwarr disagrees.)
      • use trap 0 for cleanup.
      • don’t use /tmp unless you’re on a Mac. You’re creating open season for tempfile races.
      • use ${1:?errmsg} to ensure you’re getting called with enough parameters.

      Also, see Insufficiently known POSIX shell features, linked in the comment thread.

      Assuming it’s not actually a satire, @kfirlavi should be commended for sharing his ideas, which is an important part of the process of learning, but he doesn’t seem to realize that he’s still at a very basic level of competence with bash scripting (witness his comments looking down on bash scripts that are even worse than his), and as a result his advice is not very good.

      1. [Comment removed by author]

        1. 5

          I agree with your opinion but I think what the author of the article is trying to point out is: “How to use Bash securely” not “What to use instead of Bash”.

          1. [Comment removed by author]

            1. 2

              It’s not good advice. It’s terrible advice. See my longer top-level comment for details.

              1. 1

                Do you recommend using Bash at all given how hard it is to use correctly?

                1. 2

                  Yes, because there isn’t a plausible alternative. I mean Plan9 rc is less bug-prone but where do you have it installed?