Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 24 Nov 2006 14:21:47 +0100 (CET)
From:      Oliver Fromme <olli@lurza.secnetix.de>
To:        freebsd-standards@FreeBSD.ORG, sa2c@sa2c.net
Subject:   Re: type command bahaviour of FreeBSD's /bin/sh (Fwd: [issue426] ?hgmerge assumes FileMerge to be exist unconditionally on FreeBSD)
Message-ID:  <200611241321.kAODLlu6059664@lurza.secnetix.de>
In-Reply-To: <7a2b18c80611240418w43776195p340d1ff49ac69786@mail.gmail.com>

next in thread | previous in thread | raw e-mail | index | archive | help
NIIMI Satoshi wrote:
 > FreeBSD's /bin/sh produces:
 > | % sh -c 'type /nonexistent; echo $?'
 > | /nonexistent: No such file or directory
 > | 0

Note that the "type" utility is normally not called
with a full path, but with a command name.  In that
case it behaves correctly:

$ type asdfg
asdfg: not found
$ echo $?
127

If you have a full path name and need to know whether
it exists, you should rather use the "test" utility
instead of "type".  The purpose of "type" is to find
out how a _name_ would be interpreted when given as
a command (i.e. keyword, builtin, alias, shell function
or $PATH expansion).

 > Does the current behaviour of /bin/sh's type command conform to the standards?

SUSv3/POSIX2001 is not very clear, unfortunately.  It
doesn't exactly explain how the "type" utility should
behave when given a non-existing absolute path.  I tend
to believe that it's not a bug in FreeBSD, but rather
a valid interpretation of the standard.

 > > Because of the above feature (bug?), testing
 > > "/Developer/.../FileMerge" always succeeds and used unconditionally.
 > > I made a patch to work around this.

As I said above, it is _wrong_ to use "type" for testing
the existence of a file whose full path is known.  Use
"test" (a.k.a. "[") for that purpose:

if [ -f "$FULLPATH" ]; then
        # ... found
else
        # ... not found
fi

Even if you need to find out whether a name expands to
an external command, it is _not_ sufficient to only check
the return code of "type".  You also need to parse the
output in order to check whether it returned a full path
(as opposite to "shell builtin", "alias" or whatever).
In fact it is non-trivial, because the output format of
the "type" builtin is not standardized and varies between
shells.  Therefore, if you need to find a command in the
$PATH list, then it's better to do that yourself using
a shell loop, like this:

FULLPATH=""
OLD_IFS="$IFS"
IFS=":"
for DIR in $PATH; do
        if [ -x "$DIR/$COMMAND" ]; then
                FULLPATH="$DIR/$COMMAND"
                break
        fi
done
IFS="$OLD_IFS"
if [ -n "$FULLPATH" ]; then
        echo "Found: $FULLPATH"
else
	echo "$COMMAND not found"
fi

My conclusion is that you should _never_ use "type" in
portable shell scripts.

Best regards
   Oliver

-- 
Oliver Fromme,  secnetix GmbH & Co. KG, Marktplatz 29, 85567 Grafing
Dienstleistungen mit Schwerpunkt FreeBSD: http://www.secnetix.de/bsd
Any opinions expressed in this message may be personal to the author
and may not necessarily reflect the opinions of secnetix in any way.



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200611241321.kAODLlu6059664>