Bash

bash/zsh 掛鉤 - 僅在未找到匹配文件時才添加到 PATH

  • February 21, 2022

我正在尋找一個 bash/zsh鉤子,當找不到命令時呼叫它。

假設我執行一些任意執行檔:

xyz foo --bar
  1. 說 bash/zsh 找不到執行檔。
  2. 有沒有辦法處理“未找到”,然後將一些庫動態載入到 PATH 中?

像這樣的東西:

function xyz {
 if ! test -f xyz; then
    load_libs xyz
 fi
 command -v xyz;
}

類似這個函式的東西,但它適用於未知的執行檔。

所以一般來說它看起來像:

function on_not_found {
 if ! test -f "$1"; then
    load_libs "$1"
 fi
 command -v "$@";
}

兩者都zsh具有bash掛鉤函式,您可以定義這些函式來處理找不到命令的情況。它被稱為command_not_found_handleinbashcommand_not_found_handlerin zshbash’s 啟發,但錯字/誤稱已修復)。

但是請注意,它們在子程序中執行(更不用說子shell 可能找不到該命令),因此無法更改您的shell 環境。

你可以這樣做:

zsh

command_not_found_handler() {
 {
   if (( ! IN_CNFH++)) && load_lib "$1"; then
     "$@"
   else
     print -ru2 -- "$functrace[1]: command not found: $1"
     return 127
   fi
 } always {
   (( IN_CNFH-- ))
 }
}

IN_CNFH如果命令成功後仍然找不到,避免無限遞歸的部分load_lib

如果您已經有一個command_not_found_handler(某些系統在其 zsh 預設配置中提供了一個,以在找不到命令時建議要安裝的軟體包的名稱),您可以在它之前插入類似的內容:

functions[command_not_found_handler]='
 {
   if (( ! IN_CNFH++)) && load_lib "$1"; then
     "$@"
     return
   fi
 } always {
   (( IN_CNFH-- ))
 }
 '$functions[command_not_found_handler]

重擊

bash 中的等效項如下所示:

command_not_found_handle() {
 local ret
 if (( ! IN_CNFH++)) && load_lib "$1"; then
   "$@"
   ret=$?
 else
   printf >&2 '%s\n' "$BASH_ARGV0: $1: command not found: $1"
   ret=127
 fi
 (( IN_CNFH-- ))
 return "$ret"
}

或者增量變體,以防已經存在command_not_found_handle

eval 'command_not_found_handle() {
 local ret
 if (( ! IN_CNFH++)) && load_lib "$1"; then
   "$@"
   ret=$?
   (( IN_CNFH-- ))
   return "$ret"
 fi
 (( IN_CNFH-- ))
 '"$(typeset -f command_not_found_handle | tail -n +2)"'
}'

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