如何验证程序是否存在,以返回错误并退出,或继续执行脚本?

看起来应该很容易,但这让我很为难。


当前回答

我想说,由于悬挂别名,没有任何可移植和100%可靠的方法。例如:

alias john='ls --color'
alias paul='george -F'
alias george='ls -h'
alias ringo=/

当然,只有最后一个是有问题的(林戈没有冒犯!)。但从command-v的角度来看,它们都是有效的别名。

为了拒绝像ringo这样的悬空命令,我们必须解析shell内置别名命令的输出并递归到它们中(这里命令-v并不优于别名)。没有任何可移植的解决方案,即使是特定于Bash的解决方案也相当乏味。

注意,类似这样的解决方案将无条件拒绝别名ls='ls-F':

test() { command -v $1 | grep -qv alias }

其他回答

hash foo 2>/dev/null:适用于Zshell(Zsh)、Bash、Dash和ash。

type-p foo:它似乎可以使用Z shell、Bash和ash(BusyBox),但不能使用Dash(它将-p解释为一个参数)。

命令-vfoo:适用于Z shell、Bash、Dash,但不适用于ash(BusyBox)(-ash:command:not found)。

还要注意,内置的ash和Dash不可用。

假设您已经遵循了安全壳做法:

set -eu -o pipefail
shopt -s failglob

./dummy --version 2>&1 >/dev/null

这假设命令可以以这样的方式调用,即它(几乎)什么都不做,比如报告其版本或显示帮助。

如果找不到伪命令,Bash将退出并返回以下错误。。。

./my-script: line 8: dummy: command not found

这比其他命令-v(和类似的)回答更有用,也更不冗长,因为错误消息是自动生成的,并且还包含相关的行号。

which命令可能有用。男子谁

如果找到可执行文件,则返回0;如果找不到或不可执行,则返回1:

NAME

       which - locate a command

SYNOPSIS

       which [-a] filename ...

DESCRIPTION

       which returns the pathnames of the files which would
       be executed in the current environment, had its
       arguments been given as commands in a strictly
       POSIX-conformant shell. It does this by searching
       the PATH for executable files matching the names
       of the arguments.

OPTIONS

       -a     print all matching pathnames of each argument

EXIT STATUS

       0      if all specified commands are 
              found and executable

       1      if one or more specified commands is nonexistent
              or not executable

       2      if an invalid option is specified

这样做的好处是,它可以确定可执行文件在运行环境中是否可用-这节省了一些问题。。。

它可能更简单,只是:

#!/usr/bin/env bash                                                                
set -x                                                                             

# if local program 'foo' returns 1 (doesn't exist) then...                                                                               
if ! type -P foo; then                                                             
    echo 'crap, no foo'                                                            
else                                                                               
    echo 'sweet, we have foo!'                                                    
fi                                                                                 

将foo更改为vi以激发其他条件。

我必须检查Git是否作为部署CI服务器的一部分安装。我最后的Bash脚本如下(Ubuntu服务器):

if ! builtin type -p git &>/dev/null; then
  sudo apt-get -y install git-core
fi