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"

相關文章
相關標籤/搜索