4

Inspired by this answer: When I run type -p in the command prompt, it reliably tells me the path if the command exists:

pi@raspberrypi:~ $ type -p less
/usr/bin/less
pi@raspberrypi:~ $ type -p asdf
pi@raspberrypi:~ $ 

However, when used in a in a script it is as if the -p parameter is interpreted as a command of itself. It seems the type command ignores it as its option, because there is always some rogue text of -p not found in the result. It breaks the rest of the script:

#!/usr/bin/sh

main() { for mycommand in $1; do echo Checking $mycommand loc="$(type -p "$mycommand")" echo $loc if ! [ -f "$loc" ]; then echo I think I am missing $mycommand fi done }

main "less asdf"

Output of the script:

Checking less
-p: not found less is /usr/bin/less
I think I am missing less
Checking asdf
-p: not found asdf: not found
I think I am missing asdf

Can you please help me out here? Is there something about the shell on a raspberry pi that is causing this?

  • 2
    (1) Please get out of the habit of passing multiple arguments by passing a single string that contains multiple values, separated by whitespace.  (2) Please get into the habit of quoting shell variables: "$1", "$mycommand", "$loc", etc.  (3) If you’re getting inconsistent behavior from shell builtin commands, perhaps you’re using different shells. Quite possible (probably?) your interactive shell is bash. /usr/bin/sh is probably not bash. Try writing the script with #!/bin/bash, #!/usr/bin/bash, or #!/usr/bin/env bash as the first line. – G-Man Says 'Reinstate Monica' Mar 22 '22 at 08:11
  • Thanks for these tips. I just started learning bash, didn't know that there is much difference between sh and bash. – fleetingbytes Mar 22 '22 at 08:17
  • @Zababa, sh is a standard language for which there exist several interpreter implementations such as bash, ksh or dash, like C is a standard language for which there exist several compiler implementations such as gcc or clang (implementations of the cc standard command). bash supports extensions to that language, like gcc support extensions. – Stéphane Chazelas Mar 22 '22 at 08:26

2 Answers2

14

-p is not a standard option for the type command¹. The type utility itself, though standard is optional in POSIX (only required on systems implementing XSI, though that is required to obtain UNIX compliance certification).

Instead of type, you can use command -v to check for availability of a command. No need to check its output, command will tell you via its exit status if it succeeded to find the command or not (regardless of whether it's an external command found in $PATH, a builtin or a function):

#!/usr/bin/sh -

main() { for mycommand do printf >&2 '%s\n' "Checking $mycommand" if ! command -v -- "$mycommand" > /dev/null 2>&1; then printf >&2 '%s\n' "I think I am missing $mycommand" fi done }

main less asdf

command is a mandatory POSIX utility. The -v option to command used to be optional, but it's not any longer in the latest version of the POSIX specification.

Also remember that echo can't be used to display arbitrary data, -- must be used to separate options and non-options, errors (and in general diagnostics including progress/advisory information) should preferably go to stderr.


¹ it is however an option supported by the type builtin of the bash, mksh, ksh93, busybox ash, zsh and yash shells². In mksh and yash, it's meant to search the command in the standard $PATH (as returned by getconf PATH for instance), in zsh, it's for searching the command only in $PATH, not in aliases/builtins/functions. Same in ksh93, except that it also only prints the path of the found command. In bash (where it's used to be -path; still supported though no longer documented), type -p succeeds but prints nothing if the command is a builtin, and prints the path only like in ksh93 when it's an external command. In busybox ash, it behaves similarly to command -v

² all more or less conformant interpreter implementations of the standard sh language at least when invoked as sh, though that doesn't prevent them from supporting extensions over that language in areas where the standard leaves the behaviour unspecified like here.

0
#!/bin/sh
command="somecommand"
if [ "$(which "$command")" != "" ]; 
then
    echo "command found"
else
    echo "command not found"
fi
Jeff Schaller
  • 67,283
  • 35
  • 116
  • 255