6

I was reading about the differences between /bin/sh and /bin/bash and came across this interesting question/answer: here

I made a comment to the answer asking this same question in my title to which he replied with an updated answer:

How can you find out what /bin/sh points to on your system?

The complication is that /bin/sh could be a symbolic link or a hard link. If it's a symbolic link, a portable way to resolve it is:

> % file -h /bin/sh
> /bin/sh: symbolic link to bash 

If it's a hard link, try

> % find -L /bin -samefile /bin/sh 
> /bin/sh 
> /bin/bash

I tried this and had trouble so I thought I would make a separate question.

My results from the linked answer:

>file -h /bin/sh
>/bin/sh: executable (RISC System/6000) or object module

>find -L /bin -samefile /bin/sh
>find: bad option -samefile

What am I missing? I'm running AIX:

>oslevel -s
7100-03-03-1415
Community
  • 1
  • 1
exit_1
  • 1,240
  • 4
  • 13
  • 32
  • Run `man find`. It's a program that is very finnicky about options on different systems. Your version's `-samefile` will have a different name if it exists at all. – Mad Physicist Apr 20 '17 at 20:36
  • 1
    Looks like `/bin/sh` is indeed an executable on your system, not a symbolic link. Keep in mind that it is not necessarily "pointing to" some other shell executable. And apparently your `find` utility is not the gnu find utility and not compatible to that one. Which is not surprising for a commercial Unix variant. – arkascha Apr 20 '17 at 20:36
  • @arkascha. The question is not if it's an executable vs a symlink at this point. The question is if it's a hard link to the bash executable. – Mad Physicist Apr 20 '17 at 20:39
  • I ran a search for "samefile" after running `man find` and returned no results. So does this mean that my 'find' utility just doesn't support that flag? – exit_1 Apr 20 '17 at 20:43
  • 1
    AIX's `find` utility supports `-inum`. Get the `inode` from `ls -i /bin/bash` then use `find /bin -inum inode` and see if `/bin/sh` will turn up. Or just compare the `inodes` of `ls -i /bin/sh /bin/bash`. – alvits Apr 20 '17 at 20:48
  • As with some other non-standard flags, -samefile is a convenience (like -delete) provided by GNU. There is a simple workaround: to use the "inconvenient" version, often involving -exec. See my answer – Mad Physicist Apr 20 '17 at 21:04
  • @MadPhysicist I did understand that question quite well. But that first test the OP performed cannot distinguish between a hard link and a file, that is why the outcome of that test indicates a file. That is all I said. – arkascha Apr 20 '17 at 21:07
  • 1
    Hard links are the filesystem pointer structures used for regular files. The hard link is a reference to the inner data structures of the filesystem. You cannot tell the difference between a regular file and a hard link, because all regular files are accessed through hard links. A symbolic link is a file that contains a path, and this path is used to point to another file. The data inside the symbolic link does not point to an inner data structure of the filesystem. This is why a symbolic link can point to a separate filesystem, while a hard link cannot. – Fred Apr 20 '17 at 21:55

8 Answers8

4

If you need to programatically test if they are the same, you can use stat to query the inode of /bin/sh and compare with the inode of /bin/bash.

if [ $(stat -L -c %i /bin/sh) -eq $(stat -L -c %i /bin/bash) ]; then
    .....
fi

If you just need to see with your eyes if they are the same run the stat commands and see if they return the same inode number.

stat -L -c %i /bin/sh
stat -L -c %i /bin/bash
alvits
  • 6,550
  • 1
  • 28
  • 28
3

Since you are only searching through bin anyway, you can bypass find entirely and just check if sh and bash are hard links to the same file:

test /bin/sh -ef /bin/bash

OR

[ /bin/sh -ef /bin/bash ]

This is not as reliable as running find on all the possibilities, but it's a good start. While AIX find doesn't support -samefile, it does support -exec, which can be combined with the command above to simulate the same functionality:

find -L /bin -exec test /bin/sh -ef '{}' ';'
Mad Physicist
  • 107,652
  • 25
  • 181
  • 264
2

Check for GNU Bash

I'm going to answer your question in a different way, because it's actually simpler to find out if sh is GNU Bash (or something else that responds to a --version flag) than it is to chase inodes. There's also the edge case where the shell is renamed rather than linked, in which case mapping links won't really help you find an answer.

For example, to interrogate /bin/sh on macOS:

$ /bin/sh --version
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin16)
Copyright (C) 2007 Free Software Foundation, Inc.

Alternatively, you can grep (or similar) for the string bash to capture the exit status. For example:

# Close stderr in case sh doesn't have a version flag.
if sh --version 2>&- | grep -qF bash; then
  echo "sh is bash"
else
  echo "sh isn't bash"
fi

Of course, /bin/sh could be some other shell besides bash or the original bourne shell, but that's outside the scope of your original question. However, many shells such as ksh and tcsh also support the version flag, so judicious use of a case statement could help you extend the test to determine exactly which shell binary /bin/sh really is.

Todd A. Jacobs
  • 81,402
  • 15
  • 141
  • 199
1

As the answer you commented on says, -samefile isn't a standard feature of find. Neither is -inum, which searches based on an explicitly given inode number. But if your find supports that, use it.

POSIX ls supports -i, which prints the inode numbers. If find doesn't have -inum, all you need to do is go through all plausible files /bin/sh could be a hard link with...

Though before that, you could check if the file even has any other hard links, ls -l is required to show the number of links:

$ ls -l /bin/bash
-rwxr-xr-x 1 root root 1029624 Nov  5 23:22 /bin/bash
           ^ here

Of course, there's no requirement for /bin/sh to be linked to anything. It could be just another program. (Or even an identical copy of some of other file, though I don't think that's very likely.)

ilkkachu
  • 6,221
  • 16
  • 30
1

You can just use :

ls -l /bin/sh
  • 2
    Hi, I think the question is a bit more complex than the solution you contributed. Consider expanding or removing. – Eddy Mar 23 '21 at 22:32
  • How is this not complex enough? OP appears to be running a strange system for that to happen and he didn't really explain what was his confusion. This is exactly what I was looking for and it answers the question in the title if nothing else. – Deoxal Jul 02 '21 at 16:41
0

You can also do readlink -f /bin/sh. For me it points to /bin/dash.

solstice333
  • 3,399
  • 1
  • 31
  • 28
0

I can not really see the point of this exercise.

/bin/sh is a POSIX shell and bash has extensions to the POSIX standard that /bin/sh does not support.

If you are writing a POSIX shell script, use /bin/sh. If you are writing a bash shell script, use bash.

Do not try to write a bash script that will be executed with /bin/sh, and don't try to programatically try to determine the abilities of the current shell based on what /bin/sh (or the current interpreter) is linked to. Instead, make the script executable and use the correct #!-line for the script.

Kusalananda
  • 14,885
  • 3
  • 41
  • 52
0

On mac, you can just do la /private/var/select. The output would look something like this.

total 0
lrwxr-xr-x  1 root  wheel     9B Aug 24  2022 sh -> /bin/bash
kooskoos
  • 4,622
  • 1
  • 12
  • 29