Opinion on best practice...

Steven D'Aprano steve+comp.lang.python at pearwood.info
Tue Feb 5 20:55:50 EST 2013


Chris Angelico wrote:

> Python is not an "excellent option". It's a bad fit for shell
> scripting, it just happens to be way better than a weak shell. Having
> grown up on command.com, I found OS/2's cmd.exe to be a massive
> improvement, and Windows's cmd.exe to be rather less impressive... but
> both of them pale into insignificance compared to bash.

I have to disagree with much of this. bash is a poorly designed language
which, in my opinion, is only good enough for short (under 20 lines)
throw-away scripts.

[begin rant]

bash has terse *and* cryptic syntax even less maintainable than Perl. E.g.
this is, apparently, the right way to get the length of an array called R:

rlen=${#R[@]}

(taken from here:

http://www.bashcookbook.com/bashinfo/source/bash-4.2/examples/functions/array-stuff

so I hope that they know what they're talking about.)

Note that sometimes # begins a comment, and sometimes it doesn't.

This is how you test whether something is not the name of a directory:

[[ -d $dir ]] || {
  echo "$FUNCNAME: $dir is not a directory" >&2
  return 2
}


http://www.bashcookbook.com/bashinfo/source/bash-4.2/examples/functions/emptydir

Arithmetic requires either calling an external program, or special magic
syntax:

z=`expr $z + 3`
i=$(( i + 1 ))

Spaces are magic -- these two lines do radically different things:

i = j
i=j

There's also a "let" command, but it's a kludge:

k=$(( i+2 )) 
let k=i+2

are equivalent, but 

k=$(( i*2 ))
let k=i*2

are not!

bash is even more weakly typed than Perl. As far as I can tell, bash is
completely untyped -- everything is text, all the time, even arrays.

[steve at ando ~]$ cat testarray.sh
colors=('Blue' 'Red')
echo $((colors + 2))

[steve at ando ~]$ sh testarray.sh
2

Quotation marks have magic powers, and the rules for them are so complicated
that working out how to correctly quote expressions is probably the single
most difficult part of bash scripting.

bash teaches bad programming habits, such as reliance on global and
environment variables, and lacks "modern" (30+ years old) features such as
exception handling, objects, and even proper functions that return a
result. Yes, that's right, bash functions communicate their result by
side-effect.

http://www.linuxjournal.com/content/return-values-bash-functions

Because bash scripts are mostly written by non-programmers, the culture as a
whole has a cargo-cult mentality about it. I'm sure that there are some
people who actually do know bash, it's strengths and weaknesses, well, but
in my experience most people just blindly copy code snippets and recipes
around without really understanding them. As a consequence, we have this:

http://partmaps.org/era/unix/award.html

Almost nothing in bash is portable. Because bash does so little, and relies
on external programs for so much, even if you write the bash parts portably
(which basically means writing for the Bourne shell, which is even more
lacking than bash), you *still* aren't portable because there's no
guarantee that the external programs exist or do what you expect on some
other system.

To do anything meaningful in bash, you need to be an expert on passing work
off to other programs, e.g. sed, awk, grep, tr, cut, ed, ps, dc, wc, ...
any of which may be missing, or have different semantics from what you
expect (ps in particular is notorious for the widely variable command
switches it takes), or output their results in unexpected ways.

Pretty much of all bash scripting is kludge on top of kludge, special
behaviour, small syntax differences making large differences in behaviour,
surprising gotchas, side-effects and magic. If you took the Zen of Python,
and pretty much reversed everything, you might have the Zen of Bash:

Implicit is better than explicit.
Complex is better than simple.
Complicated is better than complex.
Dense is better than sparse.
Readability doesn't count.
Special cases break the rules.
Errors should pass silently.
In the face of ambiguity, guess.
There should be many obscure ways to do it.
Namespaces are terrible, let's make everything global!

I would not hesitate to use Python, or some other high-level language like
Ruby, over bash for anything non-trivial that I cared about. It might not
be as terse and compact as a well-written bash script, but that's a *good*
thing, and a poorly-written bash script is likely to be even more verbose
and difficult to write than a poorly-written Python script.



-- 
Steven




More information about the Python-list mailing list