本文由 GPT-4 翻譯。原文為英文版,可以在此查看 English version。
這不是愚人節玩笑!
如果你已經安裝了 Golang,現在可以嘗試打開你的終端並輸入 ??。你會發現它神奇地變成了 Golang CLI。
沒錯!這確實是 go 命令!如假包換
為什麼會這樣呢?
故事的開始:GitHub Copilot CLI#
一個月前,我收到了使用 GitHub Copilot CLI 的邀請,當時它還處於技術預覽階段。它使用 GPT 來幫助我們將自然語言翻譯成 shell 命令。
如上面的演示 GIF 所示,我們只需要輸入 ?? <instruction>,就可以讓 GPT 為我們寫下預期的命令。
相當酷。
於是我安裝了它,並在其文檔中看到了關於如何設置 ?? 別名以方便使用的部分:
... 我們建議您在 shell 中安裝
??、git?和gh?命令... 要安裝它們,請運行以下命令:eval "$(github-copilot-cli alias -- "$0")"
好的。
我正準備這樣做,但我突然想確保一下 ?? 是安全的別名。於是我輸入了 ?? 並按下回車:
➜ ~ ??
Go is a tool for managing Go source code.
Usage:
go <command> [arguments]
...
等一下....
為什麼 ?? 命令會鏈接到 go?
搜索和提問#
於是我在 Discord 群裡問了一下:
但不幸的是,沒有人知道答案。
難道是我在 .zshrc 文件中配置錯誤了嗎?檢查了一會兒,答案是否定的。我的配置看起來很好。
接下來,我在 Golang Repo 中搜索,但找不到關於 ?? 別名的任何內容。也沒有相關的 issues。
然後,我嘗試谷歌一下。但描述這個問題變得很困難。看起來似乎甚至連 "??" 的關鍵字查詢都無法被搜索引擎優先處理。搜索結果幾乎毫不相關。
看起來我是全網第一個遇到這個問題的人!
...
我放棄了。我輸入了 eval "$(github-copilot-cli alias -- "$0")" 將我的 ?? 別名設置為 github-copilot-cli,這樣只要我們忽略掉詭異的部分,其他一切看起來都很好。唯一仍然不完美的是,which ?? 仍然給我 go 二進制的位置,因為函數命令初始化只在每次啟動會話時運行。這更加令人困惑。
更多人加入了這個謎團#
在接下來的一個月裡,許多其他人也獲得了訪問 GitHub Copilot 的權限。其中一些人遇到了和我一樣的問題。
我很高興至少我不是一個人。
答案終於找到了#
終於,在今天(一個月後),這個案例被 GitHub Next 團隊的某位成員解決了:
??命令被 shell 展開為當前工作目錄中的任意兩個字符的二進制條目。
這是什麼意思?
他確實指出了大概的機制,但犯了一個錯誤 ——?? 匹配的是文件名和目錄,而不是二進制文件。再闡述一下,意思著當我們使用 ?? 時,我們在尋找當前文件夾中恰好由兩個字符組成的文件名或目錄名。
無論我們輸入多少個 ?,都適用相同的規則!
在上面的示例中,echo ?????? 列出了所有可能的長度為 6 個字符的目錄或文件名;cd ????? 則將我們帶到了唯一一個長度為 5 個字符的目錄。
也就是說:
??????->GitHub Movies Public?????->Music
所以,在我們的例子中,位於主目錄的 ?? 解析為唯一一個長度為 2 個字符的目錄 go。
??->go
如果我們在另一個沒有 go 目錄的目錄中,它就行不通了:
等等.... 還有一個問題#
我們剛才不是說 “目錄或文件名” 嗎?為什麼它會調出 go 二進制文件而不是進入 go 目錄呢?
沒錯!我知道,對吧?預期的行為應該是進入 go 目錄(對於 bash 來說,<dirname> 等同於 cd <dirname>)。
這是因為全局二進制文件位置解析具有比本地文件名或目錄更高的優先級。舉個例子:
這裡我們創建了一個名為 go 的文件,然後輸入 go 命令,它不會執行本地的 go 文件,而是執行全局的 go 二進制文件。我們需要特別輸入本地文件的相對路徑來執行它:
對於目錄,它具有類似的行為,但目錄允許我們在不使用顯式 cd 命令的情況下進行 cd。
因此,如果當前目錄中有一個名為 go 的文件或目錄,並且我們輸入 ?? 時,它將展開為此 go 文件名或目錄名,然後嘗試執行它。
我們可以用 npm 達到同樣的效果:
更有趣的是#
當我們知道 ??.. 命令會執行展開的文件名或目錄時,我們可以做一些有趣的事情。
例如,echo 一些單詞:
更好的是,為什麼不執行一些 npm 腳本呢?
只需確保腳本的每個單詞長度相同,且每個單詞的首字母按字母順序排列。
好了,希望你喜歡這篇愚人節文章。現在,將 "wow" 腳本更改為 rm -rf /,然後發送給你最好的朋友,告訴他們執行 ???。玩得開心!(開玩笑的!千萬別這麼做!)