time
、time
和 cd
實際上是做什麼的?(shell 中的反斜杠很有趣)
/usr/bin/time
在討論與 shell(bash 和 zsh) built-in之間的區別時time
,有人提到可以將\time
其用作 get 的簡寫/usr/bin/time
。首先,這似乎是一個不錯的天真的捷徑,但隨後出現了一些問題:
- 為什麼也
t\ime
有效?- 為什麼要
\cd
更改目錄,即使/usr/bin/cd
¹ 沒有?所以很明顯,
\foo
不等價於$(which foo)
。現在的問題是:在 bash 和 zsh 中觀察到的行為是否
\foo
以任何方式包含在 shell 的 POSIX 定義中,如果是,為什麼它的行為如此?腳註 1:
/usr/bin/cd
是,在我的系統上,#!/bin/sh builtin cd "$@"
t\ime
or\cd
(或"tim"e
or'cd'
or or${-##*}time
or${-+time}
以及您能想到的所有其他引用和擴展組合最終將解析為time
orcd
),是:另一種編寫方式cd
andtime
。但是,這最終會在 shell 語法解析和解釋時
cd
或之後解決。time
特別是,在 shell 關鍵字辨識和別名替換發生很久之後就會發生這種情況。因此,當 shell 在其語言中尋找關鍵字時,它並沒有辨識
ti\me
為time
shell 關鍵字。所以一個:ti\me echo test
將被 shell 辨識為一個簡單的命令,而不是
time
關鍵字後跟一個簡單的命令。然後引用 in
ti\me
將被處理(這裡反斜杠引用了m
無論如何都不需要引用的字元,引用字元被刪除,你得到time
)並且將像任何其他命令一樣查找命令(在內置命令列表time
中,函式和執行檔$PATH
。很可能會在/bin/time
這裡)對於
cd
,shell 語言中沒有cd
關鍵字,只有一個cd
內置命令(優先於您的/usr/bin/cd
)。但是,如果您確實為cd
(likealias cd=pushd
) 定義了別名,則同樣如此。由於別名替換很早就完成了,在刪除引號之前,如果你有一個別名 forcd
而不是一個 for\cd
(請注意,沒有多少 shell 允許其中包含反斜杠的別名),然後編寫:\cd dir
你確保你的
cd
別名沒有被替換。簡而言之,引用命令名稱或其任何部分可防止其被視為 shell 關鍵字(關鍵字如
while
,for
,if
,{
…僅time
在某些shell 中是關鍵字),並繞過您可能擁有的別名.但是,它不會強制該命令解析為 in 中的執行檔
$PATH
,該命令仍會首先在函式(您可以通過 do 解決command time cmd...
)和內置函式(您可以通過 do 解決env time cmd...
,儘管我不知道具有內置time
命令的外殼)。請注意,在某些 shell 中,引用也可能對
typeset
/declare
/export
/ … 系列的特殊內置函式的行為產生影響。local
請參閱局部變數賦值是否需要引號?詳情。