globbing 何時發生(此處)
當我按下輸入時
(cd <somewhere>/; ls -gG S09E03*
我預計不是與任何文件匹配的目錄
S09E03*
(我已經驗證過),但該命令顯示的資訊與我想要的文件有關。所以看起來我的shell(更新檔Debian Buster上的zsh,即版本5.7.1)直到它位於正確的目錄中(即在.之後
cd
)才進行globbing。cd
是一個內置的(它基本上必須是),所以我猜外殼知道我希望它發生在哪裡?我完全沒戲了嗎?它是否與子外殼有關 -
(cd <somewhere1>; ls -l <prefix>*; cd <somewhere2>; ls -l <prefix>*)
顯示有關兩個不同文件的資訊,所以我不這麼認為,但我可能(再次)錯了?或者是其他什麼東西延遲了 globbing(不管我怎麼想。
<somewhere>
很長,所以我試圖避免在輸出中獲得該路徑ls
ls -gG
因為我知道文件的所有者和組在我想比較某些屬性的文件之間會有所不同
Shell(不僅僅是 zsh)在擴展並執行命令之前完成對命令的解析。
- 解析根據shell 語法分解輸入。此步驟包括辨識哪些字元是單詞分隔符、保留作品、命令運算符、重定向運算符、此處的文件標記、引號等。
- 執行命令會評估命令運算符(
;
、&
、|
等),並且對於簡單命令,執行參數分配、重定向和從左到右的擴展。- 執行呼叫外部命令、內置命令或函式(如果有)。
請注意,我在這裡只給出一個非常籠統的概述。一些極端情況可能很棘手並且依賴於 shell,我不會在這篇文章中討論這些。
當給定時
(cd subdir/; ls -gG S09E03*)
,shell首先對其進行解析以獲得以下結果:
一個子shell執行:
兩個命令的序列:
- 一個由兩個普通單片語成的簡單命令:
cd
,subdir/
(沒有帶引號的字元)。- 一個由三個普通單片語成的簡單命令:
ls
,-gG
,S09E03*
(沒有帶引號的字元)。這與 shell 所做的工作相同,例如,如果它正在處理函式定義
f () { (cd subdir/; ls -gG S09E03*) }
一旦它解析了命令,shell就會執行它。它為 subshell 構造創建一個 subshell。在 subshell 內部,它首先展開然後執行第一個簡單命令,然後展開然後執行第二個命令。目前目錄
subdir/
在執行第一個簡單命令期間更改為。的擴展S09E03*
是發生通配步驟的地方,稍後發生。順便說一句,子外殼只是一個不會改變任何東西的細節。重要的是
;
分開兩個命令,第一個命令在第二個命令之前執行。並不是說“shell 知道我想讓它發生在哪裡”——它正在發生的地方發生。命令參數的擴展總是發生在與命令本身相同的目錄中(執行命令的任何部分都不能更改其目前目錄,除了可以呼叫內置函式或在函式內部執行的最後一步)。