原文出處: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"