Bash

如何防止不受支持的“shopt”選項在我的 .bashrc 中導致錯誤?

  • August 24, 2019

我在一個相對異構的環境中工作,我可能在不同的 HPC 節點、VM 或我的個人工作站上執行不同版本的 Bash。因為我將登錄腳本放在 Git 儲存庫中,所以我想.bashrc全面使用相同的(ish),沒有很多“如果這個主機,那麼……”類型的混亂。

喜歡Bash ≤ 4.1 的預設行為,它cd $SOMEPATH在按鍵cd /the/actual/path時會擴展Tab。在 Bash 4.2 及更高版本中,您需要shopt -s direxpand重新啟用此行為,並且直到4.2.29才可用。不過,這只是一個例子;另一個可能相關shopt的選項complete_fullquote(儘管我不知道它的確切作用)可能也改變了 v4.2 的預設行為。

但是,direxpand早期版本的 Bash 無法辨識,如果我嘗試shopt -s direxpand在我.bashrc的 .

-bash: shopt: direxpand: invalid shell option name

我想做的是包裝一個條件,shop -s direxpand以一種健壯的方式在 Bash > 4.1 上啟用該選項,而不會惹惱舊版本的 Bash(,不僅僅是將錯誤輸出重定向到/dev/null)。

檢查是否direxpand存在於的輸出中shopt,如果存在則啟用它:

shopt | grep -q '^direxpand\b' && shopt -s direxpand

我看不出將錯誤重定向到/dev/null. 如果您希望您的程式碼具有健壯性set -e,請使用常見的習慣用法… || true

shopt -s direxpand 2>/dev/null || true

如果您想在選項不存在的情況下執行一些備份程式碼,請使用以下返回狀態shopt

if shopt -s direxpand 2>/dev/null; then
 … # the direxpand option exists
else
 … # the direxpand option does not exist
fi

但是如果你真的不喜歡重定向錯誤,你可以使用完成機制來執行自省。這假設您沒有 bash ≤ 2.03 且沒有可程式完成的過時機器。

shopt_exists () {
 compgen -A shopt -X \!"$1" "$1" >/dev/null
}
if shopt_exists direxpand; then
 shopt -s direxpand
fi

這種方法避免了分叉,這在某些環境(例如 Cygwin)上很慢。直截了當的也是如此2>/dev/null,我認為您無法在性能上擊敗它。

引用自:https://unix.stackexchange.com/questions/498857