Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Bourne is not bash, or: Read, echo, and backslash (brandonmintern.com)
38 points by BrandonM on March 25, 2012 | hide | past | favorite | 25 comments


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.


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}'


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.


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).


    #!/usr/bin/env python
also ensures your scripts look for the virtualenv python when virtualenv is activated, but the system python when virtualenv is deactivated.


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'. ;-)


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...


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".


Due to the same problem you mention, many Linux shell startup scripts are a mess as well. The /etc/profile actually reads in a /etc/bash.bashrc if $BASH is set on Ubuntu, instead of taking the correct approach of letting Bash handles its own startup. One some system (either Redhat or Ubuntu or CentOS, can't remember which) ends up reading in bash's startup scripts in the wrong order - and the wrong number of times.

Instead of cramming things in /etc/profile (which really should only be about environment variables, where ~/.bashrc should pick most of them up from the parent process), just having ~/.bash_login read ~/.bashrc solves getting all your interactive bash startup commands into one file (assuming the /etc/skel/.* is used during account creation so users don't have to set that up themselves).


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.


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.


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


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...


POSIX specified way to get results you are expecting is "command -p echo", as POSIX does not guarantee where the utilities are located, on the other hand it guarantees that all utilities that are implemented as shell builtins while they don't need to (eg. cd makes sense only as builtin) must also be present on filesystem.


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...


Debian comes with dash as sh by default.


What do you have debconf set at? When dash is installed dpkg asks if it should install the link. If you want to change it:

  dpkg-reconfigure -p low dash


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


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:~$


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...


Did you try:

  dpkg-reconfigure -p low dash


I don't doubt that that is the case for you. I am saying when dash was installed dpkg asks if it should install the link and you said to install the link. If you want to change it or see the question again:

  dpkg-reconfigure -p low dash


My fault. I should have realised that this is on a VPS where the OS is installed from a pre-configured image. I guess the VPS provider configured it to use bash.


No worries. I have been a debian user for years. All the doubters above did not bother to run dpkg-reconfigure like you did. Its a shame that people are going to argue about something but never actually do any research. The worst part is that this thread reinforced incorrect beliefs about debian.

On a related note set the debconf priority to low so that you always know the dpkg decisions that go into the creation of your system. That way you are not ignorant like the doubters above...


When dash was installed debconf asked if you wanted to link /bin/dash to /bin/sh. You said no, others said yes...




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: