Unix/Linux - Shell 輸入/輸出重定向



本章將詳細討論 Shell 輸入/輸出重定向。大多數 Unix 系統命令從您的終端接收輸入,並將生成的輸出傳送回您的終端。命令通常從標準輸入讀取其輸入,預設情況下,標準輸入是您的終端。類似地,命令通常將其輸出寫入標準輸出,這同樣也是您的終端。

輸出重定向

通常用於標準輸出的命令輸出可以輕鬆地改定向到檔案。此功能稱為輸出重定向。

如果將符號 `>`file 附加到任何通常將其輸出寫入標準輸出的命令,則該命令的輸出將寫入檔案,而不是您的終端。

檢查以下 **who** 命令,該命令將命令的完整輸出重定向到 users 檔案。

$ who > users

請注意,終端上沒有顯示任何輸出。這是因為輸出已從預設的標準輸出裝置(終端)重定向到指定的檔案。您可以檢查 users 檔案的完整內容:

$ cat users
oko         tty01   Sep 12 07:30
ai          tty15   Sep 12 13:32
ruth        tty21   Sep 12 10:10
pat         tty24   Sep 12 13:07
steve       tty25   Sep 12 13:03
$

如果命令的輸出重定向到一個檔案,並且該檔案已經包含一些資料,則這些資料將丟失。請考慮以下示例:

$ echo line 1 > users
$ cat users
line 1
$

您可以使用 `>>` 運算子將輸出追加到現有檔案,如下所示:

$ echo line 2 >> users
$ cat users
line 1
line 2
$

輸入重定向

就像命令的輸出可以重定向到檔案一樣,命令的輸入也可以從檔案重定向。如同使用 **大於號 >** 用於輸出重定向,**小於號 <** 用於重定向命令的輸入。

通常從標準輸入獲取輸入的命令可以以這種方式從檔案重定向其輸入。例如,要計算上面生成的 users 檔案中的行數,您可以執行以下命令:

$ wc -l users
2 users
$

執行後,您將收到以下輸出。您可以透過從 users 檔案重定向 **wc** 命令的標準輸入來計算檔案中的行數:

$ wc -l < users
2
$

請注意,wc 命令的兩種形式產生的輸出有所不同。在第一種情況下,檔名 users 與行數一起列出;在第二種情況下,則沒有。

在第一種情況下,wc 知道它正在從 users 檔案讀取輸入。在第二種情況下,它只知道它正在從標準輸入讀取輸入,因此它不顯示檔名。

Here Document

**Here Document** 用於將輸入重定向到互動式 shell 指令碼或程式。

我們可以透過為互動式程式或互動式 shell 指令碼提供所需的輸入,在 shell 指令碼中執行互動式程式,而無需使用者操作。

**Here Document** 的一般形式為:

command << delimiter
document
delimiter

在這裡,shell 將 **<<** 運算子解釋為一個指令,讀取輸入直到找到包含指定分隔符的行。然後,所有直到包含分隔符的行之前的輸入行都將被送入命令的標準輸入。

分隔符告訴 shell **Here Document** 已完成。如果沒有分隔符,shell 將永遠繼續讀取輸入。分隔符必須是一個不包含空格或製表符的單個單詞。

以下是用於計算總行數的命令 **wc -l** 的輸入:

$wc -l << EOF
   This is a simple lookup program 
	for good (and bad) restaurants
	in Cape Town.
EOF
3
$

您可以使用 **Here Document** 使用您的指令碼列印多行,如下所示:

#!/bin/sh

cat << EOF
This is a simple lookup program 
for good (and bad) restaurants
in Cape Town.
EOF	

執行後,您將收到以下結果:

This is a simple lookup program
for good (and bad) restaurants
in Cape Town.

以下指令碼執行與 **vi** 文字編輯器的會話,並將輸入儲存到檔案 **test.txt** 中。

#!/bin/sh

filename=test.txt
vi $filename <<EndOfCommands
i
This file was created automatically from
a shell script
^[
ZZ
EndOfCommands

如果使用 vim 作為 vi 執行此指令碼,則您可能會看到如下輸出:

$ sh test.sh
Vim: Warning: Input is not from a terminal
$

執行指令碼後,您應該會看到以下內容新增到檔案 **test.txt** 中:

$ cat test.txt
This file was created automatically from
a shell script
$

丟棄輸出

有時您需要執行命令,但不想在螢幕上顯示輸出。在這種情況下,您可以透過將其重定向到檔案 ** /dev/null** 來丟棄輸出:

$ command > /dev/null

這裡 command 是您要執行的命令的名稱。檔案 ** /dev/null** 是一個特殊檔案,它會自動丟棄其所有輸入。

要丟棄命令的輸出及其錯誤輸出,請使用標準重定向將 **STDERR** 重定向到 **STDOUT**:

$ command > /dev/null 2>&1

這裡 **2** 代表 **STDERR**,**1** 代表 **STDOUT**。您可以透過將 STDOUT 重定向到 STDERR 來在 STDERR 上顯示訊息,如下所示:

$ echo message 1>&2

重定向命令

以下是您可以用於重定向的完整命令列表:

序號 命令 & 說明
1

pgm > file

pgm 的輸出重定向到 file

2

pgm < file

程式 pgm 從 file 讀取輸入

3

pgm >> file

pgm 的輸出追加到 file

4

n > file

來自描述符為 **n** 的流的輸出重定向到 file

5

n >> file

來自描述符為 **n** 的流的輸出追加到 file

6

n >& m

將來自流 **n** 的輸出與流 **m** 合併

7

n <& m

將來自流 **n** 的輸入與流 **m** 合併

8

<< tag

標準輸入從此處開始,直到下一行開頭處的 tag

9

|

獲取一個程式或程序的輸出,並將其傳送到另一個程式或程序

請注意,檔案描述符 **0** 通常是標準輸入 (STDIN),**1** 是標準輸出 (STDOUT),**2** 是標準錯誤輸出 (STDERR)。

廣告