Unix 系統的命令列操作中,管道和重導向是資料流處理的關鍵技術。管道(|)將一個命令的輸出作為另一個命令的輸入,實作多個命令的串聯執行。例如,ls -l | wc -l 統計當前目錄檔案數量,ls -l 的輸出直接作為 wc -l 的輸入。重導向則改變命令的輸入來源或輸出目的地。> 將命令輸出寫入檔案(覆寫),>> 則追加到檔案末尾。2> 和 2>> 分別用於重導向錯誤訊息。輸入重導向 < 則將檔案內容作為命令的輸入。這些技術搭配命令群組和流程控制,能大幅提升工作效率。命令群組使用 {} 或 () 將多個命令組合,{} 在當前 Shell 執行,() 則在子 Shell 執行。流程控制則運用 &&(AND)和 ||(OR)等邏輯運算元控制命令執行流程,例如 command1 && command2 僅在 command1 成功執行後才執行 command2。tee 命令同時將輸出顯示在螢幕和寫入檔案,方便監控和記錄。環境變數如 PATH 和 HOME 影響系統行為,可透過 export 命令設定。熟練掌握這些技巧,能有效管理系統資源、簡化操作流程,並提升自動化指令碼的編寫能力。
管道與輸出重導向
在 Unix/Linux 命令列中,管道(pipe)是一個強大的工具,用於將一個命令的輸出作為另一個命令的輸入。這種機制允許我們將多個命令連線在一起,形成一個完整的處理Pipeline。管道運算元 | 是實作這一功能的關鍵。
基本概念與範例
考慮以下命令:
ls -l | wc -l
這條命令的功能是輸出當前目錄中的檔案總數。具體來說,ls -l 列出當前目錄中的所有檔案和目錄,並將結果寫入標準輸出。接著,管道運算元 | 將這些輸出轉送給 wc -l 命令,wc -l 計算標準輸入中的行數,從而得出檔案的總數。
環境變數與自定義
Unix/Linux 的 Shell 環境包含一組預定義的變數,稱為環境變數。這些變數用於控制和組態實用程式的行為。環境變數的值通常由作業系統或微服務在程式外部設定。以下是一些常見的環境變數:
HOME: 使用者的家目錄路徑。PATH: 搜尋 Shell 命令的路徑。PS1: 預設提示符。TERM: 終端型別。HOSTNAME: Unix 主機名。
Shell 提供了多種命令來自定義環境,例如 export 和 set 命令。
Shell 程式語言
Shell 本身具有自己的程式語言,可以用來撰寫 Shell 指令碼。與 C 或 C++ 等編譯型語言不同,Shell 程式語言是解釋型的,這意味著每一條指令在執行前都會被解釋和檢查錯誤。
Shell 程式設計涉及使用 Shell 命令和程式設計結構來撰寫指令碼。這些指令碼是由簡單文字命令組成的序列,可能包含內部或外部 Shell 命令和程式設計結構,如條件陳述式、迴圈、變數、表示式等。
各類別 Shell 的比較
Unix 系統中的 Shell 並不是內建的,而是一個獨立的程式。不同的 Shell 提供不同的功能和特性。以下是一些常見 Shell 的分類別和特性:
Bourne Shell 家族
-
Bourne Shell(/bin/sh):
- 最早的 Unix Shell,由 Steve Bourne 開發。
- 支援演算法式程式設計語言(ALGOL)風格。
-
Korn Shell(/bin/ksh):
- 由 David Korn 開發,是 Bourne Shell 的超集。
- 包含 C Shell 的互動功能和 Bourne Shell 的語法。
- 新增了陣列、檔名完成、指令別名、函式等功能。
-
Bourne Again Shell(Bash, /bin/bash):
- 由 Brian Fox 開發,目前由 Chester Ramey 輸人維護。
- 支援無限大小的陣列、路徑補全、整數算術等功能。
C Shell 家族
-
C Shell(/bin/csh):
- 由 Bill Joy 開發,指令看起來像 C 陳述式。
- 支援指令歷史記錄、別名、檔名補全、作業控制等功能。
-
TENEX C Shell(tcsh, /bin/tcsh):
- C Shell 的相容版本,常用於 Linux。
- 支援透過箭頭鍵滾動指令歷史記錄和指令列表。
Meta Characters 與萬用字元
Shell 中有一些特殊符號稱為 Meta Characters(元字元),它們不會被傳遞給命令,而是由 Shell 本身解釋。以下是一些常見的元字元及其意義:
?: 檔名替換萬用字元(單字元)。*: 檔名替換萬用字元(多字元)。[]: 檔名替換萬用字元(括號內任何字元)。<: 輸入重導向。<<: 輸入重導向(here document)。>: 輸出重導向。>>: 輸出重導向(附加)。#: 評論。(): 指令群組。"cmd": 指令替換。$(Cmd): 指令替換。|: 管道。;: 指令序列。&: 背景執行指令。||: OR 邏輯運算元。&&: AND 邏輯運算元。$: 展開變數值。\: 防止下一個字元被解釋。
延伸閱讀:如何防止元字元被解釋
有時候我們需要避免某些元字元被解釋。Shell 提供了三種方法來防止這些元字元被解釋:
- 使用反斜槓 (
\):在元字元前加上反斜槓可以避免其被解釋。 - 使用雙引號 (
" "):將指令放在雙引號內可以避免其中某些元字元被解釋。 - 使用單引號 (
' '):將指令放在單引號內可以完全避免其中任何元字元被解釋。
命令標準輸入/輸出
在 Unix/Linux 系統中,程式通常會自動連線到終端機。終端機以通用檔案表示。當沒有指設定檔案路徑時,命令會從這個通用檔案取得輸入並將輸出送回同一檔案。預設情況下,這個通用檔案就是終端機。
UNIX 標準輸入輸出與重導向
在 UNIX 系統中,標準輸入、標準輸出和標準錯誤是處理命令輸入與輸出的基本機制。這些機制讓我們可以靈活地控制命令的輸入來源和輸出目的地,進而提升操作的效率與靈活性。
標準輸入與標準輸出
UNIX 系統中的標準輸入(stdin)、標準輸出(stdout)和標準錯誤(stderr)分別由三個特殊的檔案來表示:
- 標準輸入(stdin):檔案名稱為
/dev/stdin,通常對應到鍵盤。 - 標準輸出(stdout):檔案名稱為
/dev/stdout,通常對應到螢幕。 - 標準錯誤(stderr):檔案名稱為
/dev/stderr,通常也對應到螢幕。
每個檔案都有一個對應的檔案描述符(file descriptor),這些描述符是系統用來操作檔案的基礎:
- stdin:檔案描述符為 0
- stdout:檔案描述符為 1
- stderr:檔案描述符為 2
標準輸入與輸出的預設行為
當我們執行一個命令時,它會預設從標準輸入讀取資料並將結果寫入到標準輸出。例如,當我們在終端機中執行 cat file1 命令時,cat 會從標準輸入(通常是鍵盤)讀取資料並將 file1 的內容顯示在螢幕上。
重導向的概念
重導向(redirection)是 UNIX 中一個強大的功能,它允許我們將命令的輸入或輸出重新指向其他檔案或裝置。這在處理大量資料或需要將資料儲存到檔案中時非常有用。
輸出重導向
有兩個基本的重導向運算元:
>:將命令的輸出寫入指定的檔案,如果檔案已存在則會覆寫其內容。>>:將命令的輸出追加到指定的檔案的末尾,如果檔案不存在則會建立新的檔案。
例如:
$ ls -l > file1
這條命令會將 ls -l 的結果寫入 file1 檔案中。如果 file1 已經存在,其內容會被覆寫。
另一個例子:
$ cat file1 >> file2
這條命令會將 file1 的內容追加到 file2 檔案的末尾。
安全重導向
為了避免意外覆寫重要的檔案,UNIX 提供了 noclobber 選項。啟用 noclobber 後,試圖覆寫已存在檔案時會報錯而不是覆寫。
啟用 noclobber 的方法:
% set noclobber (C shell)
$ set -o noclobber (bash 和 ksh)
如果需要強制覆寫已存在的檔案,可以使用 !:
% ls -l > !file1
常見的標準 I/O 重導向操作
以下是一些常見的標準 I/O 重導向操作:
| 功能 | C shell | bash/ksh |
|---|---|---|
| 將 stdout 送到檔案 | prog > file | prog > file |
| 將 stderr 送到檔案 | prog 2> file | prog > file |
| 將 stdout 和 stderr 送到同一個檔案 | prog >& file | prog > file 2>&1 |
| 從檔案取 stdin | prog < file | prog < file |
| 將 stdout 機加到檔案末尾 | prog » file | prog » file |
| 將 stderr 加到檔案末尾 | prog 2» file | prog » file |
| 將 stdout 和 stderr 加到同一個檔案末尾 | prog »& file | prog » file |
| 與標準輸入迴圈 | prog « c | prog « c |
| 透過管道將 stdout送到另一個程式 | prog | prog2 | prog | prog2 |
| 透過管道將 stdout 和 stderr送到另一個程式 | prog |& prog2 | prog 2>&1 | prog2 |
輸入重導向
除了輸出重導向外,UNIX 中也支援輸入重導向。這允許我們從檔案中讀取資料而不是從鍵盤。
例如:
$ mail George < mail_file
這條命令會將 mail_file 檔案中的內容傳送給 George。
再舉一個例子:
Case 1: wc -l file1
output: 10
Case 2: wc -l < file1
output: 10 file1
在 Case 1 中,shell 命令列決定要執行 wc -l 命令來計算 file1 的行數。
在 Case 2 中,shell 命令列發現了輸入重導向運算元 <,接下來會從檔案中取得輸入以便進行計算。
使用 Unix 命令列進行輸入輸出重導向與流程控制
在 Unix 系統中,命令列是我們與系統互動的主要工具。透過輸入輸出重導向與流程控制,我們可以更靈活地處理資料和控制命令的執行。以下將詳細介紹這些功能及其應用。
重導向標準輸入與標準輸出
重導向是指將命令的輸入或輸出改變至其他檔案或裝置。例如,我們可以將一個檔案的內容當作命令的標準輸入,或者將命令的標準輸出寫入另一個檔案。
假設我們有一個檔案 file1,並且想要使用 wc 命令計算其中的字元數、字數和行數。通常我們會這樣做:
$ wc file1
這個命令會顯示 file1 的統計資料。如果我們想要將 file1 的內容作為 wc 的標準輸入,可以這樣做:
$ wc < file1
這樣,wc 命令會讀取 file1 的內容,並顯示其統計資料。
注意:同一個命令中不可以同時使用輸入和輸出重導向。
重導向錯誤訊息
在 Unix 系統中,錯誤訊息通常會和標準輸出一起顯示在螢幕上。例如,當我們執行以下命令時:
$ ls -l file1 file2
如果 file2 不存在,系統會顯示錯誤訊息:
ls: cannot access 'file2': No such file or directory
-rwxr-xr-x 1 user group 532 May 20 15:31 file1
這裡,錯誤訊息和正常的目錄列表都顯示在螢幕上。如果我們想要將錯誤訊息重導向到另一個檔案中,可以這樣做:
$ ls -l file1 file2 2> error_log
這樣,錯誤訊息會被寫入 error_log 檔案中。
我們也可以同時重導向標準輸出和錯誤訊息到不同的檔案:
$ ls -l file1 file2 1> output_log 2> error_log
這樣,標準輸出會被寫入 output_log 檔案中,而錯誤訊息則會被寫入 error_log 檔案中。
多個命令的群組與管道
命令群組
在 Unix 中,我們可以將多個命令群組在一起執行。有兩種主要的群組方式:
{ command-list ; }( command-list )
第一種方式會在當前的 shell 中執行所有命令,而第二種方式則會在子 shell 中執行所有命令。例如:
$ (cd x; rm junk)
這個命令會在子 shell 中切換到 x 目錄並刪除 junk 檔案,不會改變當前 shell 的工作目錄。
命令管道
管道(pipe)允許我們將一個命令的輸出作為另一個命令的輸入。例如,如果我們想要列出當前目錄中的所有檔案和目錄,然後將結果列印預出來,可以這樣做:
$ ls -l | lpr
這個命令會列出當前目錄中的所有檔案和目錄(使用 ls -l),然後將結果送到印表機(使用 lpr)。
管道可以用來處理大量資料。例如,如果我們想要檢視當前目錄中的所有檔案和目錄,並且每次只顯示一頁資料,可以這樣做:
$ ls -l | more
這樣,ls -l 的輸出會被逐頁顯示。
tee 命令和環境變數
tee 命令
tee 命令允許我們同時將命令的輸出顯示在螢幕上並寫入檔案中。例如:
$ ls -l | tee file_list
這個命令會列出當前目錄中的所有檔案和目錄(使用 ls -l),然後同時顯示在螢幕上並寫入 file_list 檔案中。
如果我們不想覆寫現有的檔案內容,可以使用 -a 選項來追加資料:
$ ls -l | tee -a file_list
UNIX環境變數
環境變數是預定義的變數,用來控制使用者環境。常見的環境變數包括 PATH 和 HOME。
- PATH 變數:列出系統搜尋命令的目錄。
- HOME 變數:指定使用者的主目錄。
環境變數可以在 shell 中設定或修改。例如:
export PATH=$PATH:/new/directory
export HOME=/new/home/directory
這些變數對於系統執行非常重要,因為它們決定了許多基本功能的行為。
流程控制與實際應用
玄貓總結重導向與流程控制可以大幅提升工作效率與自動化程度。透過合理運用重導向、管道、以及環境變數等技術工具配合實務經驗及思考過程展開技術選型分析與應用評估是技術工作者不可或缺之核心能力。