定位 zsh 中函數的來源

定位 zsh 中函數的來源

我在 zsh shell 中遇到了這個煩人的問題,其中在某處聲明了一個函數,並且該函數名為“cp”,因此它覆蓋了正常的 cp 行為。我試圖找到函數聲明,但找不到。我已經查看了 .zshrc 的正常位置以及 .zshrc 中包含的各種其他來源,但到目前為止什麼也沒有。

我嘗試過的其他事情:

  • grep -r 'function cp' .(從~)
  • whence -f cp(給出函數定義,但不給出聲明的位置)

有任何想法嗎?

答案1

首先,可以在沒有function關鍵字的情況下定義函數,因此更好的搜索

grep 'cp()' .*

這將搜尋諸如.zshrc.profile之類的文件。如果什麼也沒找到,您可能還想查看 . 載入的各種檔案zsh。這些列在最後man zsh

FILES
       $ZDOTDIR/.zshenv
       $ZDOTDIR/.zprofile
       $ZDOTDIR/.zshrc
       $ZDOTDIR/.zlogin
       $ZDOTDIR/.zlogout
       ${TMPPREFIX}*   (default is /tmp/zsh*)
       /etc/zsh/zshenv
       /etc/zsh/zprofile
       /etc/zsh/zshrc
       /etc/zsh/zlogin
       /etc/zsh/zlogout    (installation-specific - /etc is the default)

預設$ZDOTDIR應該是你的$HOME.因此,此命令應該找到您的違規文件:

grep 'cp()\|cp ()' ~/.zshenv ~/.zprofile ~/.zshrc ~/.zlogin /etc/zsh/zshenv \
 /etc/zsh/zprofile /etc/zsh/zshrc /etc/zsh/zlogin 

我添加了,\|因為函數名稱和函數本身之間也可以有空格。最後,@丹尼斯指出如果使用關鍵字,括號也可以省略function。因此,為了更加安全,請執行以下操作:

grep -E 'function cp|cp *\(\)' ~/.zshenv ~/.zprofile ~/.zshrc ~/.zlogin \
  /etc/zsh/zshenv /etc/zsh/zprofile /etc/zsh/zshrc /etc/zsh/zlogin 

答案2

我今天需要這樣做,發現whence -v輸出包含函數定義的檔案。

$ whence -v function_name
function_name is a shell function from /path/to/file

答案3

較新版本的 zsh(自 5.4 起,在提交中新增34f70c5)支援$functions_source數組作為zsh/parameter模組的一部分(文件:)man zshmodules

functions_source

此唯讀關聯數組將已啟用函數的名稱對應到包含函數來源的檔案的名稱。

對於已加載的自動加載函數,或使用絕對路徑標記為自動加載,或已使用“ functions -r”解析其路徑的自動加載函數,這是為自動加載找到的文件,解析為絕對路徑。

對於在腳本或來源檔案主體中定義的函數,這是該檔案的名稱。在本例中,這是該檔案最初使用的確切路徑,可能是相對路徑。

對於任何其他函數,包括在互動式提示中定義的任何函數或路徑尚未解析的自動載入函數,這是空字串。然而,只要函數存在,散列元素就會按照定義進行報告:該散列的鍵與 的鍵相同$functions

所以,你可以做

echo $functions_source[cp]

答案4

特爾登的回答已經為您提供了適當的grep命令來捕獲函數定義的所有可能變體。

我想補充兩點。

  1. 取得文件列表,這些文件是實際上讀入(例如,非標準檔案可能來自另一個檔案!),您可以zsh在啟用該SOURCE_TRACE選項的情況下呼叫:

    $ zsh -o sourcetrace
    +/etc/zshenv:1> <sourcetrace>
    +/home/user/.zshrc:1> <sourcetrace>
    +/home/user/.zcompdump:1> <sourcetrace>
    +/home/user/.zshrc-last:1> <sourcetrace>
    
  2. 使用這個 ,,grep-approach'' 你不會捕捉以下函數自動載入透過autoload內建的.所以,也檢查一下你的fpath

    $ for i ($fpath) { ls -l "$i"/cp }
    

相關內容