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.

14
  • 2
    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! Commented Jul 19, 2015 at 17:50
  • 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. Commented Jul 19, 2015 at 17:54
  • 1
    I think I just don't understand your goal or motivation here, sorry. "writing zsh scripts compatible with dash is not a good idea"? I happen to think that writing portable shell scripts is a good idea! (In which case they're not called zsh scripts or dash scripts but sh scripts.) I also don't understand your comment about generating shell scripts using perl — you are talking about autogenerated code here? Commented Jul 19, 2015 at 18:05
  • 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. Commented Jul 19, 2015 at 18:25
  • 1
    you don't need to know what sh is. just use syntax which will work with any of them. Commented Jul 19, 2015 at 19:48

1 Answer 1

5

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)

Another unusual case is Windows. git bash in this case:

$ readlink -f $(which sh)
/usr/bin/sh
11
  • No, because /bin/sh is not necessarily a symlink. Commented Jul 19, 2015 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). Commented Jul 19, 2015 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... Commented Jul 19, 2015 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. Commented Jul 19, 2015 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. Commented Jul 19, 2015 at 20:55

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.