如何从Bash脚本检查程序是否存在?


2207

我将如何以返回错误并退出或继续执行脚本的方式来验证程序是否存在?

看起来应该很容易,但是一直让我很沮丧。


什么是“程序”?它是否包含函数和别名?which为此返回true。type如果不带参数,则保留字和shell内置函数将另外返回true。如果“程序”的意思是“可执行文件$PATH”,那么请参见此答案
汤姆·黑尔

Answers:


3045

回答

兼容POSIX:

command -v <the_command>

对于Bash特定的环境:

hash <the_command> # For regular commands. Or...
type <the_command> # To check built-ins and keywords

说明

避免which。它不仅是您为了执行很少工作而启动的外部过程(意味着诸如hashtypecommand更便宜的内建函数),还可以依靠内建函数来实际执行所需的操作,而外部命令的效果很容易因系统之间。

为什么要在乎?

  • 许多操作系统有which甚至不设置退出状态,这意味着if which foo甚至不会在那里工作,并会始终报告foo存在,即使它没有(注意,一些POSIX炮弹似乎对这样做hash太)。
  • 许多操作系统都会which做一些自定义和邪恶的事情,例如更改输出甚至挂接到包管理器。

因此,请勿使用which。而是使用以下方法之一:

$ command -v foo >/dev/null 2>&1 || { echo >&2 "I require foo but it's not installed.  Aborting."; exit 1; }
$ type foo >/dev/null 2>&1 || { echo >&2 "I require foo but it's not installed.  Aborting."; exit 1; }
$ hash foo 2>/dev/null || { echo >&2 "I require foo but it's not installed.  Aborting."; exit 1; }

(次要注释:有些建议2>&-会相同,2>/dev/null但更短– 这是不正确的2>&-关闭FD 2会在尝试写入stderr时在程序中导致错误,这与成功写入并丢弃输出有很大不同。 (很危险!)

如果您的哈希爆炸是,/bin/sh那么您应该关心POSIX所说的。typehash的退出代码不是POSIX定义的非常好,hash当该命令不存在时(看来还没有成功),可以成功退出typecommand的退出状态已由POSIX很好地定义,因此可能是最安全的使用状态。

bash但是,如果您的脚本使用了POSIX规则,那么两者都不再重要,type并且hash变得非常安全。type现在具有-P仅搜索PATHhash的副作用,它会散列命令的位置(以便下次使用时可以更快地查找),这通常是一件好事,因为您可能需要检查它的存在才能真正使用它。

作为一个简单的示例,这是一个运行的函数(gdate如果存在),否则date

gnudate() {
    if hash gdate 2>/dev/null; then
        gdate "$@"
    else
        date "$@"
    fi
}

34
@Geert:&> / dev / null部分隐藏了'foo'不存在时发出的'type'消息。回声上的>&2确保将错误消息发送到标准错误而不是标准输出;因为那是惯例。它们都出现在您的终端上,但是标准错误绝对是错误消息和意外警告的首选输出。
lhunath

5
-P标志不以“上海”的工作,如stackoverflow.com/questions/2608688/...
momeara

128
对于不熟悉bash中“高级” i / o重定向的用户:1)2>&- (“ close输出文件描述符2”,其为stderr)具有与2> /dev/null; 相同的结果;2)>&2是的快捷方式1>&2,您可能将其识别为“将stdout重定向到stderr”。有关更多信息,请参见Advanced Bash脚本指南的I / O重定向页面
mikewaters 2011年

9
@mikewaters ABS看起来相当先进,并且描述了各种bash和非bash CLI功能,但是它在许多方面都非常疏忽,并且没有遵循良好的实践。我的评论中没有足够的空间来撰写评论;但我可以粘贴的错误代码一些随机的例子:while read element ; do .. done <<< $(echo ${ArrayVar[*]})for word in $(fgrep -l $ORIGINAL *.txt)ls -l "$directory" | sed 1d ,{{对于在seq $BEGIN $END}},......许多人都试图联系作者,并提出改进,但它没有wiki和请求都落在聋子的耳朵。
lhunath

56
@mikewaters 2>&-一样的2>/dev/null。前者关闭文件描述符,而后者仅将其重定向到/dev/null。您可能不会看到错误,因为程序会尝试在stderr上通知您stderr已关闭。
nyuszika7h 2014年

574

以下是检查命令是否存在$PATH 以及是否可执行的可移植方式:

[ -x "$(command -v foo)" ]

例:

if ! [ -x "$(command -v git)" ]; then
  echo 'Error: git is not installed.' >&2
  exit 1
fi

需要执行可执行检查,因为如果在中找不到具有该名称的可执行文件,则bash返回一个非可执行文件$PATH

还要注意,如果在较早的版本中存在与可执行文件同名的不可执行文件,则$PATHdash会返回前者,即使后者将被执行。这是一个错误,并且违反了POSIX标准。[ 错误报告 ] [ 标准 ]

此外,如果您要查找的命令已定义为别名,则此操作将失败。


4
command -v甚至会为非可执行文件生成路径吗?也就是说,-x真的必要吗?
einpoklum

5
@einpoklum -x测试文件是否可执行,这就是问题所在。
肯·夏普

3
@KenSharp:但这似乎是多余的,因为command本身会对其可执行性进行测试-是吗?
einpoklum

13
@einpoklum是的,这是必要的。实际上,即使这种解决方案也可能在一个极端的情况下失败。感谢您引起我的注意。dash,bash和zsh在$PATH执行命令时都会跳过不可执行的文件。但是,的行为command -v非常不一致。在破折号中,它将返回中的第一个匹配文件$PATH,无论它是否可执行。在bash中,它返回中的第一个可执行文件匹配项$PATH,但是如果不存在,则可以返回一个非可执行文件。并且在zsh中,它将永远不会返回不可执行的文件。
nyuszika7h 17-10-26

4
据我所知,这dash是三分之一中唯一不符合POSIX标准的产品;[ -x "$(command -v COMMANDNAME)"]将在其他两个中工作。似乎已经报告了该错误,但尚未得到任何答复:bugs.debian.org/cgi-bin/bugreport.cgi?bug=874264
nyuszika7h 17-10-26

208

我同意不鼓励使用它which,他的解决方案对Bash用户完全有效。但是,为了更便于携带,command -v应改为使用:

$ command -v foo >/dev/null 2>&1 || { echo "I require foo but it's not installed.  Aborting." >&2; exit 1; }

命令command符合POSIX。有关其规格,请参见此处:命令-执行一个简单的命令

注意:type兼容POSIX,但type -P不兼容。


3
与上面相同- exit 1;杀死xterm(如果从那里调用)。
用户未知

1
这在标准sh上不起作用:您&>不是有效的重定向说明。
jyavenard 2012年

7
@jyavenard:这个问题被标记为bash,因此更简洁的bash特定的重定向符号 &>/dev/null。但是,我同意你的意见,真正重要的是可移植性,我已经使用标准的sh redirect相应地编辑了答案>/dev/null 2>&1
GregV'3

为了进一步改善该答案,我将做两件事:1:使用“&>”来简化它,就像乔什的答案一样。2:将{}分成多行,在回显之前放置一个制表符,以提高可读性
knocte

如果有人需要的话,我只是把它放在bash函数中... github.com/equant/my_bash_tools/blob/master/tarp.bash
等效

94

我在.bashrc中定义了一个函数,可以使此操作更加容易。

command_exists () {
    type "$1" &> /dev/null ;
}

这是一个用法示例(来自我的.bash_profile。)

if command_exists mvim ; then
    export VISUAL="mvim --nofork"
fi

怎么&>办?
Saad Malik


&>在您的Bash版本中可能不可用。Marcello的代码应该可以正常工作;它做同样的事情。
乔什·斯特雷

3
无法使用内置词和保留字:例如,尝试使用该字then。如果您需要可执行文件存在于中,请参阅此答案$PATH
汤姆·黑尔'18

84

这取决于您是否想知道它是否存在于$PATH变量的目录之一中,或者您是否知道它的绝对位置。如果您想知道它是否在$PATH变量中,请使用

if which programname >/dev/null; then
    echo exists
else
    echo does not exist
fi

否则使用

if [ -x /path/to/programname ]; then
    echo exists
else
    echo does not exist
fi

/dev/null/在第一个示例中,重定向到会抑制which程序的输出。


22
出于我的评论中概述的原因,您确实不应该使用“哪个”。
lhunath

39

扩展@lhunath和@GregV的答案,这是那些想要轻松地将支票放入if语句中的人的代码:

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

使用方法如下:

if exists bash; then
  echo 'Bash exists!'
else
  echo 'Your system does not have Bash'
fi

13
学习和改进的意愿必须得到回报。+1这很简单。我唯一可以添加的是command即使对于别名也可以成功,这可能有点违反直觉。与将其移动到脚本中相比,检查交互式外壳中是否存在将得到不同的结果。
Palec 2015年

1
我刚刚测试并使用了shopt -u expand_aliases忽略/隐藏别名(如alias ls='ls -F'另一个答案中提到的),shopt -s expand_aliases并通过解析了它们command -v。因此,也许它应该在检查之前设置,而在检查之后取消设置,尽管如果您未捕获并显式返回命令调用的输出,则可能会影响函数的返回值。
dragon788


16

要使用hash如@lhunath表明,在bash脚本:

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

该脚本将运行hash,然后检查最新命令(存储在中的值)的退出代码$?是否等于1。如果hash找不到foo,则退出代码为1。如果foo存在,则退出代码为0

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


8
为什么不只是if hash foo &> /dev/null; then ...呢?
贝尼·切尔尼亚夫斯基-帕斯金

9

我从来没有得到以前的答案才能在我可以访问的盒子上工作。对于一个,type已经安装(正在做什么more)。因此需要内置指令。此命令对我有用:

if [ `builtin type -p vim` ]; then echo "TRUE"; else echo "FALSE"; fi

3
方括号不是if语法的一部分,只需使用即可if builtin type -p vim; then ...。反引号实际上是古老且过时的语法,$()即使sh在所有现代系统上也都支持。
nyuszika7h

9

检查多个依赖项并将状态通知最终用户

for cmd in latex pandoc; do
  printf '%-10s' "$cmd"
  if hash "$cmd" 2>/dev/null; then
    echo OK
  else
    echo missing
  fi
done

样本输出:

latex     OK
pandoc    missing

将调整10为最大命令长度。它不是自动的,因为我没有看到一种非冗长的POSIX方法: 如何在Bash中对齐以空格分隔的表的列?

检查是否apt安装了某些软件包,dpkg -s否则请安装

请参阅:检查是否已安装apt-get软件包,如果不在Linux上,请先安装它

以前在以下地方提到过:如何检查Bash脚本中是否存在程序?


1
非冗长的方法:1)摆脱宽度说明符;2)在命令名称的printf之后添加一个空格;3)将for循环通过管道传递到column -t(util-linux的一部分)。
Patrice Levesque

8

如果您检查程序是否存在,则无论如何都可能要稍后运行它。为什么不尝试首先运行它?

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

与仅查看PATH目录和文件权限相比,检查程序是否运行更值得信赖。

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

当然,缺点是某些程序启动起来很繁琐,而有些则没有--version立即(成功)退出的选项。


6

hash foo 2>/dev/null:与Z shell(Zsh),Bash,Dashash一起使用

type -p foo:它似乎适用于Z shell,Bash和ash(BusyBox),但不适用于Dash(它解释-p为参数)。

command -v foo:适用于Z shell,Bash,Dash,但不适用于ash(BusyBox)(-ash: command: not found)。

另请注意,builtinash和Dash不可用。


4

如果可以,请使用Bash内置函数:

which programname

...

type -P programname

15
?? which不是内置的Bash。
13年

-P程序名是首选,请参见接受的答案
RobertG '16

@RobertG我所看到的-P不是POSIX。为什么是type -P首选?
mikemaccana

我本应该回答“在bash环境中首选”的说法-因为我打算回答特定于bash的先前评论。无论如何,那是几年前的-我想我还是应该再次指出标记为“已完成”的答案
RobertG

4

-v如果将POSIX_BUILTINS选项设置为<command>要测试,则该命令可以正常工作,但如果未设置则失败。(它对我有用了很多年,但是最近我遇到了一个不起作用的地方。)

我发现以下内容更加可靠:

test -x $(which <command>)

由于它测试了三件事:路径,存在和执行权限。


不起作用 test -x $(which ls)返回0,一样test -x $(which sudo),即使ls已安装并运行的和sudo甚至没有,我在跑泊坞窗容器内安装。
藻类

@algal我需要使用引号,所以test -x "$(which <command>)"
JoniVR '19

@algal也许ls是别名?我认为如果命令具有参数,它将不会起作用。
AnthonyC

3

对于那些感兴趣的人,如果您想检测已安装的库,则先前答案中的任何方法均无效。我想象您要么实际检查路径(可能检查头文件等),要么像这样(如果您使用的是基于Debian的发行版):

dpkg --status libdb-dev | grep -q not-installed

if [ $? -eq 0 ]; then
    apt-get install libdb-dev
fi

从上面可以看到,查询中的“ 0”答案表示未安装该软件包。这是“ grep”的功能-“ 0”表示找到了匹配项,“ 1”表示没有找到匹配项。


10
但是,反模式cmd; if [ $? -eq 0 ]; then应重构为if cmd; then
Tripleee,

这仅适用于通过dpkgapt
Weiwei Zhou

3

这里有很多选择,但令我惊讶的是没有快速的一线服务。这是我在脚本开始时使用的:

[[ "$(command -v mvn)" ]] || { echo "mvn is not installed" 1>&2 ; exit 1; }
[[ "$(command -v java)" ]] || { echo "java is not installed" 1>&2 ; exit 1; }

这基于此处选择的答案和其他来源。


2

我想说由于aliases 悬空,没有任何可移植且100%可靠的方式。例如:

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

当然,只有最后一个是有问题的(林戈没有冒犯!)。但从alias的观点来看,所有这些都是有效的command -v

为了拒绝像这样的悬空命令ringo,我们必须解析shell内置alias命令的输出并将其递归到其中(command -v这不是alias这里的优点。)没有任何可移植的解决方案,甚至没有Bash-具体的解决方案很繁琐。

请注意,这样的解决方案将无条件拒绝alias ls='ls -F'

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

好点子。但是,从bash脚本内部运行时,别名不可见。
罗勒·穆萨

1
还有一个问题,当检查“别名”命令时它将返回false。何时应返回true。示例:测试“别名”
Basil Musa

2
我刚刚测试并使用shopt -u expand_aliases忽略/隐藏这些别名,shopt -s expand_aliases并通过显示它们command -v
Dragon788

1

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

有趣的which是,它可以确定可执行文件在which运行环境中是否可用-它可以节省一些问题...


如果您要查找任何名为foo的可执行文件,请使用which,但是如果您要检查特定的文件/ path / to / a / named / foo,请参阅我的回答。还要注意,尽管某些完整的安装中应该包含某些最小的系统,但可能无法使用...
dmckee ---前主持人小猫

9
不要依赖于哪个退出状态。许多操作系统的操作系统甚至都没有设置退出状态(0以外
。– lhunath

1

我的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
}

1

如果您无法在这里得到答案的答案,并且无法将头发拉出后背,请尝试使用来运行相同的命令bash -c。只要看看这个so妄。这是在运行$(子命令)时真正发生的情况:

第一。它可以为您提供完全不同的输出。

$ command -v ls
alias ls='ls --color=auto'
$ bash -c "command -v ls"
/bin/ls

第二。它根本不会给您任何输出。

$ command -v nvm
nvm
$ bash -c "command -v nvm"
$ bash -c "nvm --help"
bash: nvm: command not found

差异是由外壳的交互模式和非交互模式之间的差异引起的。您的〜/ .bashrc仅在shell非登录且是交互式时才是只读的。第二个看起来很奇怪,因为这一定是由于PATH环境变量的不同引起的,但是子shell继承了环境。
Palec 2015年

在我的情况.bashrc有一个[ -z "$PS1" ] && return由前缀# If not running interactively, don't do anything,所以我想这是一个原因,在非交互模式下的.bashrc甚至明确采购于事无补。可以通过使用ss64.com/bash/source.html点运算符调用脚本来解决此问题,. ./script.sh但这不是人们想记住的每次键入的内容。
user619271

1
采购不应被采购的脚本不是一个好主意。我只想说的是,您的答案与所提问题无关,而与Bash及其(非)交互模式有关。
Palec 2015年

如果它解释了这些情况下发生的情况,那么它将是一个有用的附录。
Palec 2015年

1

这将根据位置判断程序是否存在:

    if [ -x /usr/bin/yum ]; then
        echo "This is Centos"
    fi

是的,如果您需要在sevrer,Open suse,centos,Debian中安装软件包,我添加了此命令
Klevin Kona

语法高亮显示在“ echo”行中。解决办法是什么?是否表明Bash脚本应该有所不同?
Peter Mortensen

@PeterMortensen语法突出显示已关闭,因为它无法识别它是字符串。
阿德里安

0

哈希变量有一个陷阱:例如,在命令行上,您可以输入

one_folder/process

执行流程。为此,one_folder的父文件夹必须位于$ PATH中。但是,当您尝试哈希此命令时,它将始终成功:

hash one_folder/process; echo $? # will always output '0'

4
“为此,one_folder的父文件夹必须位于$PATH”-这完全不正确。尝试一下。为了使它起作用,one_folder必须在当前目录中
2016年

0

我第二次使用“命令-v”。例如:

md=$(command -v mkdirhier) ; alias md=${md:=mkdir}  # bash

emacs="$(command -v emacs) -nw" || emacs=nano
alias e=$emacs
[[ -z $(command -v jed) ]] && alias jed=$emacs

0

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

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

3
有条件的是没有用的,以运行apt-get的启动时间为模,因为apt-get将被满足,如果已经安装了git-core则退出。
2011年

3
它的启动时间不可忽略,但更重要的动机是sudo:没有条件,它将始终停止并要求输入密码(除非您最近进行了sudo操作)。顺便说一句,这样做可能很有用,sudo -p "Type your password to install missing git-core: "这样提示不会突然出现。
贝尼·切尔尼亚夫斯基-帕斯金

0

为了模仿Bash type -P cmd,我们可以使用POSIX兼容env -i type cmd 1>/dev/null 2>&1

man env
# "The option '-i' causes env to completely ignore the environment it inherits."
# In other words, there are no aliases or functions to be looked up by the type command.

ls() { echo 'Hello, world!'; }

ls
type ls
env -i type ls

cmd=ls
cmd=lsx
env -i type $cmd 1>/dev/null 2>&1 || { echo "$cmd not found"; exit 1; }

7
为什么要对此表示反对?这实际上在您的哪些系统上有效?type似乎是builtin在大多数炮弹所以这不行,因为env使用execvp运行command所以command不可能是一个builtin(和builtin将始终是相同的环境中运行)。这种失败对我来说在bashksh93zshbusybox [a]shdash所有这些都提供type一个shell内建。
AdrianFrühwirth2014年

0

如果没有任何外部type命令可用(如想当然这里),我们可以使用POSIX兼容的env -i sh -c 'type cmd 1>/dev/null 2>&1'

# Portable version of Bash's type -P cmd (without output on stdout)
typep() {
   command -p env -i PATH="$PATH" sh -c '
      export LC_ALL=C LANG=C
      cmd="$1"
      cmd="`type "$cmd" 2>/dev/null || { echo "error: command $cmd not found; exiting ..." 1>&2; exit 1; }`"
      [ $? != 0 ] && exit 1
      case "$cmd" in
        *\ /*) exit 0;;
            *) printf "%s\n" "error: $cmd" 1>&2; exit 1;;
      esac
   ' _ "$1" || exit 1
}

# Get your standard $PATH value
#PATH="$(command -p getconf PATH)"
typep ls
typep builtin
typep ls-temp

至少在使用Bash 4.2.24(2)的Mac OS X v10.6.8(Snow Leopard)command -v ls上,与moved不匹配/bin/ls-temp


0

如果你想检查一个程序中存在并且是一个真正的程序,而不是一击内置命令,然后commandtypehash不适合在内置命令测试,因为它们都返回0退出状态的。

例如,有一个时间程序,它提供了比内置时间命令更多的功能。要检查程序是否存在,建议which在下面的示例中使用:

# First check if the time program exists
timeProg=`which time`
if [ "$timeProg" = "" ]
then
  echo "The time program does not exist on this system."
  exit 1
fi

# Invoke the time program
$timeProg --quiet -o result.txt -f "%S %U + p" du -sk ~
echo "Total CPU time: `dc -f result.txt` seconds"
rm result.txt

-1

脚本

#!/bin/bash

# Commands found in the hash table are checked for existence before being
# executed and non-existence forces a normal PATH search.
shopt -s checkhash

function exists() {
 local mycomm=$1; shift || return 1

 hash $mycomm 2>/dev/null || \
 printf "\xe2\x9c\x98 [ABRT]: $mycomm: command does not exist\n"; return 1;
}
readonly -f exists

exists notacmd
exists bash
hash
bash -c 'printf "Fin.\n"'

结果

 [ABRT]: notacmd: command does not exist
hits    command
   0    /usr/bin/bash
Fin.

-1

我使用它,因为它很容易:

if [ `LANG=C type example 2>/dev/null|wc -l` = 1 ];then echo exists;else echo "not exists";fi

要么

if [ `LANG=C type example 2>/dev/null|wc -l` = 1 ];then
echo exists
else echo "not exists"
fi

它使用Shell内置程序和程序的回显状态输出到标准输出,而没有输出到标准错误。另一方面,如果未找到命令,则仅将状态回显为标准错误。


-1

假设您已经遵循安全的shell做法

set -eu -o pipefail
shopt -s failglob

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

假定可以以某种方式(几乎)不执行任何命令来调用该命令,例如报告其版本或显示帮助。

如果dummy找不到该命令,则Bash退出并显示以下错误...

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

command -v由于错误消息是自动生成的,并且还包含相关的行号,因此它比其他(和类似的)答案更有用且更省时。


对于那些不擅长使用shell的人来说,这个答案是非常不清楚的,因为它没有说明应该如何使用此代码,并且与许多其他答案不同,因为dummy存在测试失败的分支是无法控制的脚本的作者。另外,它也没有解释它是如何工作的以及它如何更改执行环境的设置。
Palec

这是一个Bash问题,但值得一提的是,非POSIX shopt调用可以替换为POSIX set -f,它更短且更易于移植。该pipefail选项不支持POSIX,不过,并没有替代方案,据我所知。
Palec

@Palec我不确定这有多困难。实际上,它更简单,因为它依赖于外壳程序来让用户知道找不到该命令,并按照OP的要求以错误退出。让我知道我错过了什么:)
Adrien
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.