3

I am writing a set of scripts that I want to be portable, but I need to know whether sh on the current platform stands for bash, ksh, or ash. Is there a clear way to do it?

What comes to my mind first is to inspect which shell has which --version:

$ zsh --version
zsh 5.0.2 (x86_64-apple-darwin13.0)

$ bash --version
GNU bash, version 4.3.39(1)-release (x86_64-apple-darwin13.4.0)
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

$ ksh --version
  version         sh (AT&T Research) 93u+ 2012-08-01

$ dash --version
dash: 0: Illegal option --

$ pdksh --version
pdksh: pdksh: --: unknown option

Apart from being clumsy, this doesn't even produce results in all cases.

Edit

I need it for my bashrc/zshrc/...-like project, where I assign my current working shell to a variable, and use that variable everywhere.

I can't post my code because I need to solve the problem to enable overall cleanliness of my work. Moreover, it would be too much monkeycode... don't misunderstand it, but POSIX compatibility is too narrow to make my project small enough. I'd need to crutch on system configs otherwise.

However, I can post my UNIX Shell defining function:

PROJ_GET_SHELL () {
    local PROJ_SHELL="`ps -p $$ | tail -1 | tr ' ' '\n' | tail -1`"
    PROJ_local=(pdksh bash dash mksh zsh ksh sh)
    for i in ${PROJ_local[*]}
    do
        if ! [ -z `echo $PROJ_SHELL | grep $i` ]
        then
            echo "$i"
            break
        fi
    done
}

PS. The least bit of research shows that $SHELL doesn't change when running a shell as subprocess.

  • 1
    If your scripts are written to be portable, then by definition your scripts will run correctly under all these shells, therefore you do not need to query to find out which one is in use! – Celada Jul 19 '15 at 17:50
  • @Celeda, You are right, but they aren't enough small and ksh throws segfault when zsh and bash don't. – theoden8 Jul 19 '15 at 17:51
  • 1
    What do you mean by "aren't enough small"? Do you mean that you have a very big workload and it crashes ksh? Sounds like a bug in ksh but it also sounds like the way to portability is to be more conservative with your workload or use something other than the shell as a programming language if the task is complex and not really suited for a shell script. – Celada Jul 19 '15 at 17:54
  • @Celeda, actually, the task is to make a convenient environment to make working on unix and linux as close to my mind as It's possible. You can generate shell scripts with perl, but writing zsh scripts compatible with dash is not a good idea. Moreover, they have different environmental variables, and working in general with all shells would be too much headache when you can make if-elses in a separate func. EDITED – theoden8 Jul 19 '15 at 17:58
  • 1
    @theoden It might help to provide a more specific example to illustrate your needs. The POSIX standard was created just for the purpose of enabling people to write compatible scripts without need to test for shell version. If you have some requirement that cannot be met under POSIX, it might help if you explained it. – John1024 Jul 19 '15 at 18:25
4

On popular distributions:

$ which sh
/bin/sh
$ readlink -f /bin/sh
/bin/dash

Or more compact:

$ readlink -f $(which sh)
/bin/dash

However, some (especially embedded systems or initrd builds) have their shell directly compiled as /bin/sh or it's a hardlink (busybox)

| improve this answer | |
  • No, because /bin/sh is not necessarily a symlink. – Celada Jul 19 '15 at 20:04
  • This is a good and simple solution, but I've tried it. The problem is that I'm currently working actively with Debian (sh is linked to dash) and Darwin (sh is not a link, but a binary and is bash). – theoden8 Jul 19 '15 at 20:33
  • From my experience, dash is a base which works which almost every shell: just avoid things like switch and <<< and take care about different signal names for trap's. Or just use #!/bin/dash in your shell scripts which should be available on every POSIX distro. And yes. Don't forget testing. Unfortunately, it's not easier than that... – Daniel Alder Jul 19 '15 at 20:49
  • I can't use dash for my project, it's too dash.. I would rather use perl or python, but I can't embed it into my working shell. POSIX shell is not what I can actually use without extensions. – theoden8 Jul 19 '15 at 20:54
  • @DanielAlder don't use #!/bin/dash, use #!/bin/sh. dash's raison d'être is to be a minimal fully compliant POSIX shell aka /bin/sh implementation. If you use #!/bin/sh and write portable code then it will just work everywhere (Debian and Darwin have been mentioned in this thread but there's much more) and obviate the need for the OP's question. – Celada Jul 19 '15 at 20:55

Not the answer you're looking for? Browse other questions tagged or ask your own question.