我有非常基本的 Linux 技能,現在正在嘗試解析一些 shell 腳本。我在其中一個腳本中看到這一行:
if [ -n "$(which voltdb 2> /dev/null)" ];
我知道 /dev/null 是位元儲存桶,如果我在命令列運行 voltdb,它會列印出將執行的路徑。而且,整行顯然是一個 if 語句。但我對這裡的許多其他事情感到困惑。
- 為什麼將 2 與 /dev/null 比較?這些看起來像是不相容的類型。
- 開關 -n 有何作用?我習慣使用 rm -r filename 等開關,但 -n 似乎不與任何命令配對
- 括號有什麼作用?他們在這裡似乎有別的意思,而不是在這個表達中這個測試表達式[]是什麼意思?
基本上,這條線有什麼作用?對我來說,這裡面有太多的未知數——所以這有點像聽到一個外語句子,錯過了很多單詞,以至於你無法理解基本結構。
答案1
該程式碼片段中發生了很多事情。從內到外工作:
which voltdb 2> /dev/null
- 這裡執行的命令是which
。which
呼叫時,將查找環境變數中的所有條目PATH
以查找名為“voltdb”的命令。如果它在 中指定的目錄之一中找到名為「voltdb」的可執行文件,它將列印該可執行檔PATH
的完全限定名稱。voltdb
為了回答你的第一個問題,「2>」是重定向的一個例子。每個 Unix/Linux/*BSD 流程都有 3 個標準輸入和輸出,0 是 stdin,1 是 stdout,2 是 stderr。在命令列上執行的程式通常會將錯誤訊息列印到 stderr。因此,“2> /dev/null”並不是在數字上比較 2 和“/dev/null”,而是將任何which
錯誤輸出發送到/dev/null
,一個特殊文件,只接受任何輸入,並返回0 位元組的輸出。
除此之外,該$(...)
構造意味著“運行所包含的命令並按詞法替換此處‘$(’和‘)’之間的任何輸出”。這就是輸出替換,shell 程式所做的事情。
在輸出替換之外,片段會執行if [ -n "something" ];
,其中「某物」是which
要列印的內容。 「if」是 shell 控制流程結構,當「if」之後的命令管道以「成功」狀態退出時,會導致執行程式碼區塊。
實際上是[
一個可執行文件,它查看命令列參數直到]
. “-n”標誌通常意味著“對於非零字串長度的下一個參數為 true”。這就是你的第二個問題和第三個問題的答案。該[ ... ]
構造給出了某些邏輯條件的 true(以成功代碼退出)或 false(以失敗代碼退出)答案,在本例中為“非零字串長度”。
voltdb
最終,當該 shell 的 PATH中有一個包含執行檔的目錄時,該片段將執行 if-then-fi 或 if-then-else-fi 控制流的「true」子句。
答案2
該程式碼正在執行以下操作:
if [ -n "...." ];
如果雙引號中的程式碼執行結果為空,則 if 語句為 true。
雙引號內的代碼:
$(which voltdb 2> /dev/null)
執行該which voltdb
命令並將 STDERR(標準錯誤)上發生的該命令的任何輸出重定向到/dev/null
.基本上我們對此不感興趣,所以我們忽略它。
結果which voltdb
將傳回 PATH 上與字串 voltdb 匹配的任何可執行檔的路徑。
例子
$ which time
/usr/bin/time
$ which time 2> /dev/null
/usr/bin/time
關於2>
?
2>
是一種速記符號,用於重定向其中一個的輸出溪流這是程式運行時自動設定的。流如下:
- 0 - 標準輸入(又稱 STDIN)
- 1 - 標準輸出(又稱 STDOUT)
- 2 - 標準誤差(又稱 STDERR)
因此,如果您想要取得 STDERR 的輸出並將其刪除:
$ which time 2> /dev/null
如果您想從 STDOUT 取得輸出並將其重新導向至 STDERR: