2011-09-22 75 views
107

我在写我的第一个shell脚本。在我的脚本中,我想检查某个命令是否存在,如果没有,请安装可执行文件。我将如何检查该命令是否存在?如何检查命令是否存在于shell脚本中?

if #check that foobar command doesnt exist 
then 
    #now install foobar 
fi 
+9

刚好碰到过。我认为这是相同的问题:http://stackoverflow.com/questions/592620/check-if-a-program-exists-from-a-bash-script,但它提供了更多的细节。 –

+0

@JerryTian感谢您的链接 – Andrew

+1

可能重复[检查程序是否存在于Bash脚本](https://stackoverflow.com/questions/592620/check-if-a-program-exists-from-a-bash -script) – jww

回答

167

一般而言,这取决于你的shell,但如果使用(如破折号提供)的bash,zsh中和ksh或sh,以下应该工作:

if ! type "$foobar_command_name" > /dev/null; then 
    # install foobar here 
fi 

对于一个真正的安装脚本,你'd可能要确保type在别名为foobar的情况下不能成功返回。在bash中,你可以这样做:

if ! foobar_loc="$(type -p "$foobar_command_name")" || [ -z "$foobar_loc" ]; then 
    # install foobar here 
fi 
+0

我喜欢这个答案。我尽量不要太受我喜欢的ivants形象的影响;) –

+1

嗯...当我改变它说'如果!键入“foo”>/dev/null;'然后我得到屏幕上的输出“myscript.sh:line 12:type:foo:not found”,但是,它似乎仍然工作,因为当我说'如果!键入“ls”>/dev/null;'没有输出并且if语句没有被执行(因为它返回true)。当命令不存在时,我该如何静音输出? – Andrew

+8

安德鲁,试试'如果!键入“foo”>/dev/null 2>&1;' –

28

尝试使用type

type foobar 

例如:

$ type ls 
ls is aliased to `ls --color=auto' 

$ type foobar 
-bash: type: foobar: not found 

这是优选which的几个原因:

1)的默认which实现只支持-a选项显示所有选项,所以你必须找到一个替代版本来支持别名。

2)类型会告诉你到底你在看什么(是一个bash函数或别名或适当的二进制文件)。

3)型不需要子

4)式不能被掩盖的二进制(例如,在Linux中,如果您创建一个名为which程序出现在路径上的实际which前,东西击中了风扇。type,在另一方面,是内置在外壳[是,下属在不经意间做了这一次]

+2

你可以把它放在if/else语句(不输出到控制台)的形式吗? – Andrew

+0

而在一些自定义的Linux上,没有“哪个”命令。 – Razavi

1

which <cmd>

也看到options which supports的别名如果适用于你的情况。

$ which foobar 
which: no foobar in (/usr/local/bin:/usr/bin:/cygdrive/c/Program Files (x86)/PC Connectivity Solution:/cygdrive/c/Windows/system32/System32/WindowsPowerShell/v1.0:/cygdrive/d/Program Files (x86)/Graphviz 2.28/bin:/cygdrive/d/Program Files (x86)/GNU/GnuPG 
$ if [ $? -eq 0 ]; then echo "foobar is found in PATH"; else echo "foobar is NOT found in PATH, of course it does not mean it is not installed."; fi 
foobar is NOT found in PATH, of course it does not mean it is not installed. 
$ 

PS:注意所安装的,不是一切都可能在PATH。通常要检查某些东西是否“安装”,或者不会使用与操作系统相关的安装相关命令。例如。用于RHEL的rpm -qa | grep -i "foobar"

+0

'哪有'还有其他的陷阱 –

+0

我刚刚开始阅读'男人类型'看看它是如何更好..可能是你可以通过发布在这里保存我一些时间.. :) – Kashyap

+0

它是'帮助类型': ) –

15

Check if a program exists from a Bash script涵盖了这一点。在任何shell脚本中,如果可运行$command_name,则最好使用command -v $command_name进行测试。在bash中,你可以使用hash $command_name,它也可以散列任何路径查找的结果,或者如果你只想查看二进制文件(不是函数等),则可以使用type -P $binary_name。)

11

问题没有指定壳,因此对于使用fish (friendly interactive shell)那些:

if command --search foo >/dev/null do 
    echo exists 
else 
    echo does not exist 
end 

对于基本POSIX的兼容性,使用-v标志,该标志为--search-s的别名。

9

五种方式,4 bash和1除了为zsh中:

  • type foobar &> /dev/null
  • hash foobar &> /dev/null
  • command -v foobar &> /dev/null
  • which foobar &> /dev/null
  • (($+commands[foobar]))(zsh的只)

您可以将它们中的任何一个添加到if子句中。根据我的测试(https://www.topbug.net/blog/2016/10/11/speed-test-check-the-existence-of-a-command-in-bash-and-zsh/),推荐在bash中使用第1种和第3种方法,在速度方面推荐在zsh中使用第5种方法。

+0

[检查程序是否存在于Bash脚本](https://stackoverflow.com/q/592620/608639)特别建议不要使用'which'。 – jww

0

一个功能我在正是这种

function assertInstalled() { 
    for var in "[email protected]"; do 
     if ! which $var &> /dev/null; then 
      echo "Install $var!" 
      exit 1 
     fi 
    done 
} 

例如呼叫由安装脚本:

assertInstalled zsh vim wget python pip git cmake fc-cache 
+0

抬起头来:这会使zsh崩溃,因为 – Alvin

+0

只会在脚本外部调用此脚本或获取脚本时崩溃。如果您这样做,请将退出1更改为返回1或其他错误代码。 – mgild

+0

[检查程序是否存在于Bash脚本中](https://stackoverflow.com/q/592620/608639)特别建议不要使用“which”。 – jww

相关问题