shell中检查某个命令是否存在

原文出处:linux

http://stackoverflow.com/questions/592620/check-if-a-program-exists-from-a-bash-script shell


不要使用which,由于相对于hash、type、command等内置命令,它不只是一个功能不强大的外置命令。并且要依赖内置命令才能实现你的需求,同时在各个系统上的做用也有不一样之处。安全


为啥要在乎这些细节呢?bash

  • 不少linux发行版上的which执行完后甚至没有返回码,这就意味着在上面执行完"if which foo"就不会奏效,即便"foo"命令 不存在,系统也会报告存在,这样明显是拔苗助长。(部分POSIX风格的shell对hash命令也会有相似状况)ide

  • 不少linux发行版上的which会作一些邪恶的事情,好比改变输出结果甚至会接入到包管理器中。函数



所以,不要使用which,建议使用如下命令:ui

$ command -v foo >/dev/null 2>&1 || { echo >&2 "I require foo but it's not installed.  Aborting."; e
$ 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>&-”会关闭掉命令执行出错时产生的文件描述符“2”,这与“2>/dev/null”的命令执行成功后将结果定向到空设备中是彻底不同的。)ip


若是你的hash-bang是“/bin/sh”,那么你就须要关注一下POSIX说明。POSIX中type及hash命令的返回码定义得不是很好,hash命令貌似是命令不存在是会返回成功(type中还没有发现此现象)。POSIX中command命令的返回码定义得很好,所以command命令或许是三者中最安全的。get


若是你的脚本运行环境是bash的话,POSIX中的规则就不会形成任何影响,type和hash两个都可安全使用。type可以使用-P参数来查找命令所在路径,hash的话会有反作用,它会将命令所在的位置哈希一遍(为了提升下次的查询速度),这一般是一件好事,由于为了能使用上某个命令,你可能会检查它是否存在。hash


如下面的gnudate函数为例,若是gdate命令存在就运行之,不然运行date命令。

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

小结:

当你的shell环境是bash时,通常使用hash或type命令。

当写一个POSIX风格的脚本时,则使用"command -v"

相关文章
相关标签/搜索