

Bourne is not bash, or: Read, echo, and backslash - BrandonM
http://shebang.brandonmintern.com/bourne-is-not-bash-or-read-echo-and-backslash

======
rcthompson
I've long-since accepted that the shell syntax I learned is bash, not sh, so I
just put "#!/bin/bash" at the top of all my shell scripts.

------
viraptor
Nice summary. Also pretty much a short list of reasons why I started to write
even simple scripts in awk or python when they get too long. Another long
topic is quoting variables, $ inside strings and expansion before execution...
Opinions may vary of course, but I've found it easier to just write this (or
whatever you need) and deal with normal variables and normal lex-and-parse-
before-expansion/execution language:

    
    
        echo 'abcdefghijklm\nop
        123456789' | awk '{print}'

~~~
BrandonM
I like that approach, and I usually find myself doing the same thing. Just be
sure when writing a Python "executable" that the first line is:

    
    
      #!/usr/bin/env python
    

Since python is not a POSIX-specified utility, it might be anywhere on the
user's PATH. Using the env trampoline (it is guaranteed to be available at
/usr/bin/env) will allow your script to work on any POSIX system that has
Python installed and on the PATH.

In a brief search, I wasn't able to find a canonical location of awk defined
in POSIX, so it might be necessary to use env for that, too.

~~~
dfox
POSIX does not define canonical locations of any binaries, not even sh (Ahell
& Utilities, sh, Application Usage). Only things that are specified in POSIX
by exact path (Base Definitions, 10.1) are /dev/null, /dev/tty, /dev/console
and /tmp.

Using /usr/bin/env is common practice, but not standardized in any way. Also,
POSIX does not specify the '#!' syntax, and only documents the original
mechanism of running shell scripts (execl/vp() passes anything that is not
understood by kernel to sh).

------
erlkonig
Great article. :-)

Small nitpick with the ".sh" - it's false advertising once it's become a bash
script; but don't just go to ".bash", rather just drop it and it's set. And
soon, otherwise users write other programs depending on the script's name -
with ".sh", then you reimplement in python/perl and bemoan that your alleged
shell script is now a wolf in sheep's clothing, then reimplement it in C - and
that ".sh" is still stuck there, a strange historical note that now undermines
the entire original reason for putting an extension on it at all.

Commands shouldn't have extensions, ever, on Unix or its variants. Unix has
magic numbers and interpreter directives, DOS has extensions and the ability
to ignore them when looking up commands ... never the twain should meet.

Just saying'. ;-)

------
syntaxfree
The elephant in the room is -- it's 2006, erm, 2012, and even shell scripts
can't be expected to run reliably in lowercase-linux anymore?

... this wouldn't be a problem if Ubuntu hadn't run away with its own default
shell...

~~~
KC8ZKF
Wasn't it lowercase-linux that ran away with its own default shell? I mean,
the whole confusion starts when "/bin/sh" is a simlink to "bash".

And we haven't considered the confusion that Bash, when invoked as "/bin/sh"
behaves differently than both the Bourne shell and Bash invoked as
"/bin/bash".

------
sciurus
This is a good article; it's easy to learn shell scripting without understand
bashisms vs POSIX or keeping track of what are external commands and what are
shell builtins. This will leave you pulling your hair out later, as the
article demonstrates.

------
dredmorbius
Nit: 'man echo' doesn't show bash's built-in echo. You'd use 'help' for that.

If you want to invoke the echo executable, specify it explicity (/bin/echo).
Limitations on POSIX limitations posted by others noted.

------
KC8ZKF
Yet another way to do this is to use "/bin/echo" instead of the builtins or
printf. "/bin/echo" is part of POSIX.

~~~
BrandonM
That is true, but there are two caveats:

1\. POSIX /bin/echo does _not_ recognize any options other than "-n", and "-n"
is "implementation-defined". [0] So you end up right back at the same problem.

2\. I _highly_ recommend using built-ins where possible. Invoking /bin/echo
instead of using echo involves copying a string into an argument vector,
setting argc, loading /bin/echo, attaching std file descriptors, and forking.
All of this to print a string to stdout.

It's much better to explicitly specify the behavior you want by invoking the
appropriate interpreter, or to use /bin/sh while being sure to stick to POSIX-
compliant functionality (e.g. printf).

[0]
[http://pubs.opengroup.org/onlinepubs/009695399/utilities/ech...](http://pubs.opengroup.org/onlinepubs/009695399/utilities/echo.html)

------
dfc
The author's assessment of debian is incorrect (I can't speak for ubuntu).
Debian does not replace link /bin/sh to /bin/dash without being instructed by
the user to do so. When dash was installed dpkg queries the user about what to
do with /bin/sh. If you are unhappy with how you set your system up:

    
    
      # dpkg-reconfigure -p low dash
    

Neat unix trivia article but don't blaspheme Debian...

~~~
zokier
Debian comes with dash as sh by default.

~~~
Nick_C
Not on my new install of Debian 6 (squeeze). sh is a symlink to /bin/bash.

~~~
zokier
Very interesting. Are you sure? I get following with my squeeze, and I'm
pretty sure that I haven't configured anything.

    
    
        zokier@galleria:~$ uname -a
        Linux galleria 2.6.32-5-686 #1 SMP Thu Nov 3 04:23:54 UTC 2011 i686 GNU/Linux
        zokier@galleria:~$ lsb_release -a
        No LSB modules are available.
        Distributor ID: Debian
        Description:    Debian GNU/Linux 6.0.3 (squeeze)
        Release:        6.0.3
        Codename:       squeeze
        zokier@galleria:~$ which sh
        /bin/sh
        zokier@galleria:~$ ls -l /bin/sh
        lrwxrwxrwx 1 root root 4 Jan  1 11:38 /bin/sh -> dash
        zokier@galleria:~$ debconf-show dash
        debconf: DbDriver "passwords" warning: could not open /var/cache/debconf/passwords.dat: Permission denied
        * dash/sh: true
        zokier@galleria:~$

~~~
dfc
Your debconf-show just proves my point.

    
    
       The most common use is "debconf-show packagename", which displays all items in 
       the debconf database owned by a given package, and their current values.  
       Questions that have been asked already are prefixed with an '*'.
    

True means link /bin/sh to dash.

Its awesome to get downvoted for being correct...

