6
#!/bin/sh

foo() {
   echo "in foo"
}

type foo

checkbashisms.pl obviously does not like type, why?

$ checkbashisms.pl foo.sh
possible bashism in foo.sh line 7(type):
type foo

Is it not POSIX? But it's supported by all common shells (i.e. bash, zsh, dash, busybox sh, mksh; even in ksh; maybe just csh does not support it), should not there be a way how to suppress this warning?

1
12

type is part of POSIX, but as part of the X/Open Systems Interfaces option (XSI). The checkbashisms man page explicitly says

Note that the definition of a bashism in this context roughly equates to "a shell feature that is not required to be supported by POSIX"; this means that some issues flagged may be permitted under optional sections of POSIX, such as XSI or User Portability.

So type is flagged because it is an optional feature.

I’m not aware of any way of disabling specific warnings in checkbashisms, other than removing them from the script.

3
  • I wonder whether other other problems are the same: ('((' should be '$((') in local limit_down=$(( PAGESIZE * ((limit + PAGESIZE - 1) / PAGESIZE) )) and done <&${fd_act} => should be >word 2>&1` lists.linux.it/pipermail/ltp/2021-September/024853.html, but I can create separate questions for them.
    – pevik
    Sep 2 at 16:07
  • The former is a bug in checkbashisms (which would really need a full shell parser...). Have you tried using shellcheck instead? Sep 2 at 16:12
  • I'm sorry for not giving credit, IMHO usually official docs or link to mailing list is used as reference, but I'll do next time. shellcheck is IMHO full of false positives (not only my opinion, that's why LTP project stick to checkbashisms.
    – pevik
    Sep 3 at 6:47
7

Consider command -v foo or command -V foo instead of type foo. I've been told it's more reliable and more likely to be a builtin.

Let's test this on a $PATH executable, a builtin, a function, and an alias:

#!/bin/sh

foo() {
   echo "in foo"
}
bar=foo

for cmd in sed command foo bar; do
  type "$cmd"
  command -V "$cmd"
  command -v "$cmd"
done

Output (using dash 0.5.11):

sed is /usr/bin/sed
sed is a tracked alias for /usr/bin/sed
/usr/bin/sed
command is a shell builtin
command is a shell builtin
command
foo is a shell function
foo is a shell function
foo
bar is an alias for foo
bar is an alias for foo
alias bar='foo'

(Note: sed is not an alias! Maybe this refers to dash's hash table of command locations?)

Try running that in bash and you'll get errors from type and command -V because bash doesn't enable aliases in non-interactive scripts. Bash will also reveal the entire function definition —on multiple lines— given command -V, which is really hard to parse.

POSIX defines command's options as:

-p Perform the command search using a default value for PATH that is guaranteed to find all of the standard utilities.

-v Write a string to standard output that indicates the pathname or command that will be used by the shell, in the current shell execution environment (see Shell Execution Environment), to invoke command_name, but do not invoke command_name.

  • Utilities, regular built-in utilities, command_names including a character, and any implementation-defined functions that are found using the PATH variable (as described in Command Search and Execution), shall be written as absolute pathnames.
  • Shell functions, special built-in utilities, regular built-in utilities not associated with a PATH search, and shell reserved words shall be written as just their names.
  • An alias shall be written as a command line that represents its alias definition.
  • Otherwise, no output shall be written and the exit status shall reflect that the name was not found.

-V Write a string to standard output that indicates how the name given in the command_name operand will be interpreted by the shell, in the current shell execution environment (see Shell Execution Environment), but do not invoke command_name. Although the format of this string is unspecified, it shall indicate in which of the following categories command_name falls and shall include the information stated:

  • Utilities, regular built-in utilities, and any implementation-defined functions that are found using the PATH variable (as described in Command Search and Execution), shall be identified as such and include the absolute pathname in the string.
  • Other shell functions shall be identified as functions.
  • Aliases shall be identified as aliases and their definitions included in the string.
  • Special built-in utilities shall be identified as special built-in utilities.
  • Regular built-in utilities not associated with a PATH search shall be identified as regular built-in utilities. (The term "regular" need not be used.)
  • Shell reserved words shall be identified as reserved words.

In writing shell scripts, I highly suggest using command -v rather than type or command -V because it's the only one of the three that has a defined output. Then again, most of my scripts invoke it via a silent helper function that ignores its output altogether as it determines whether we have the command:

we_have() { command -v "$1" >/dev/null 2>&1; }

if we_have obscure-command; then
  osbcure-command …
fi
1
  • 2
    I didn't realize that command -v supports also functions, I've used it just for commands. Obviously it does.
    – pevik
    Sep 3 at 10:37
2

The command type is definitely not a bashism, since it is part of UNIX since 1984.

The type command however may not be present if you are on a tiny embedded platform that just offers rudimentary POSIX compatibility.

If you are on a platform that calls itself a UNIX-platform, the type command is mandatory because a UNIX-platform is required to support all so called XSI enhancements mentioned in the POSIX standard.

If you are looking for a halfway similar command that is required to be supported even by tiny embedded systems, you may like to use:

command -V foo

instead. Note that the uppercase -V option to command prints similar but not necessarily identical output as type.

Also Note: Neither the output format from command -V nor from type is defined by the POSIX standard.

4
  • 1
    Note that command -v/-V were also optional in POSIX prior to the 2008 edition. Sep 3 at 18:49
  • @StéphaneChazelas do you know a shell that does/did not implement these options?
    – schily
    Sep 3 at 20:11
  • type and command -v/V were removed from posh for the reason that they were not mandated by POSIX. posh like that checkbashism.pl were written to help check compliance to the Debian policy which for shell script syntax is based on POSIX with a few additions. But other than that, I don't know of real shells that don't support them (though I've not checked explicitly) Sep 3 at 20:19
  • 1
    See also bugs.debian.org/cgi-bin/bugreport.cgi?bug=397601 it looks like command -v/V have been added back very recently Sep 3 at 20:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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