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

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


当前回答

我想说,由于悬挂别名,没有任何可移植和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 }

其他回答

要像@lhunath建议的那样在Bash脚本中使用哈希:

hash foo &> /dev/null
if [ $? -eq 1 ]; then
    echo >&2 "foo not found."
fi

此脚本运行哈希,然后检查最近命令的退出代码(存储在$?中的值)?,等于1。如果hash没有找到foo,则退出代码将为1。如果存在foo,则退出代码将为0。

&>/dev/null重定向哈希的标准错误和标准输出,以便它不会出现在屏幕上,echo>&2将消息写入标准错误。

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不可用。

我的Debian服务器设置:

当多个包包含相同的名称时,我遇到了问题。

例如apache2。这就是我的解决方案:

function _apt_install() {
    apt-get install -y $1 > /dev/null
}

function _apt_install_norecommends() {
    apt-get install -y --no-install-recommends $1 > /dev/null
}
function _apt_available() {
    if [ `apt-cache search $1 | grep -o "$1" | uniq | wc -l` = "1" ]; then
        echo "Package is available : $1"
        PACKAGE_INSTALL="1"
    else
        echo "Package $1 is NOT available for install"
        echo  "We can not continue without this package..."
        echo  "Exitting now.."
        exit 0
    fi
}
function _package_install {
    _apt_available $1
    if [ "${PACKAGE_INSTALL}" = "1" ]; then
        if [ "$(dpkg-query -l $1 | tail -n1 | cut -c1-2)" = "ii" ]; then
             echo  "package is already_installed: $1"
        else
            echo  "installing package : $1, please wait.."
            _apt_install $1
            sleep 0.5
        fi
    fi
}

function _package_install_no_recommends {
    _apt_available $1
    if [ "${PACKAGE_INSTALL}" = "1" ]; then
        if [ "$(dpkg-query -l $1 | tail -n1 | cut -c1-2)" = "ii" ]; then
             echo  "package is already_installed: $1"
        else
            echo  "installing package : $1, please wait.."
            _apt_install_norecommends $1
            sleep 0.5
        fi
    fi
}

如果您检查程序是否存在,您可能会稍后运行它。为什么不先尝试运行它?

if foo --version >/dev/null 2>&1; then
    echo Found
else
    echo Not found
fi

这是一个更值得信赖的检查程序运行,而不仅仅是查看PATH目录和文件权限。

此外,您可以从程序中获得一些有用的结果,例如其版本。

当然,缺点是有些程序启动起来会很重,有些程序没有--version选项可以立即(并成功)退出。

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

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