home products tech support contact us

 Linux 技術支援    ⇒   基礎篇    進階篇    補腦篇    指令索引    中⇒ENG
版權所有, 引用請註明出處

 管線/重定向

1.0 管線與重定向
       管線(pipeline)
       重定向(redirections)
           〝1>〞或〝>〞:標準輸出重定向
           〝1>>〞或〝>>〞:標準輸出累加重定向
           〝2>〞:錯誤輸出重定向
               /dev/null 無底洞
           〝2>>〞:錯誤輸出累加重定向
           〝0<〞或〝<〞:標準輸入重定向
           〝-〞:標準輸入
           〝2>&1〞或〝&>〞:stderr 重定向 stdout
           〝1>&2〞:stdout 重定向 stderr
           〝<< 字串〞:結束輸入
           tee T型管線
1.1 指令傳回值與指令執行流程
       〝&&〞傳回值為 0 執行
       〝||〞傳回值為 ≠0 執行


1.0 管線與重定向

讓 Linux 文字界面功能有如核分裂般的強大威力,管線(pipe-line)、重定向(redirection)和萬用字元(Wildcard Characters)這三劍客功不可沒。管線和重定向可讓各別功能有限的指令產生核分裂而催化出強大的功能,。

如利用指令配合重定向如 tr -d '\r' < DOS_FILE > UNIX_FILE 就可取代指令 dos2unix ,其組合可千變萬化,是圖形操作界面所望塵莫及的。

管線(pipelines)
把某一 Linux 的指令的輸出當另一指令的輸入就是〝管線〞或叫〝管道〞(pipe-line)的基本概念。〝管線〞模擬真實世界中的水管,可接住不同方向的水流再利用,所以 UNIX/Linux 的管線符號也是一水管〝|〞。

基本上 Linux 的標準輸入(stdin)為鍵盤,標準輸出(stdout)為螢幕,以指令 cat /usr/share/dict/linux.words 為例,如沒用管線基本上輸出為螢幕,就算有一目十行的能力也不可能看清輸出。故可用〝管線〞把原要輸出到螢幕的資料接到翻頁閱讀器 moreless,最後再由 moreless 輸出到螢幕; 如 cat /usr/share/dict/linux.words | less 就可用 less 一頁頁慢慢的閱讀。

故管線的基本用法為〝某指令的 stdout | 某指令的 stdin〞,大部分有輸出到螢幕的指令都可透過管線給另一指令當輸入來源。

例:
$ ls -F /etc | grep '/$' ←列出目錄但不列出檔案(常用)
$ ls -F /etc | grep -v '/$' | less ←列出檔案但不列出目錄再經管線到 less
$ cat file | more ←輸出檔案到翻頁閱讀器
$ echo abcd | tr [:lower:] [:upper:] ←輸出經管線到 tr 改大寫輸出

管線如何應用,只受限於想像力,例如我要查詢某字元或字串的 ASCII 碼,就可利用指令 od 配合管線來達成。

例:(用管線把字串的 ASCII 碼列出)
$ echo -n 'Linux' | od -An -tx1 ←以十六進制列出字串〝Linux〞的 ASCII 碼
4c 69 6e 75 78

pipeline 的應用也可很複雜,理論上只要符合〝某一指令的 stdout 當另一指令的stdin〞即可無限延伸。如想知道已建立了那些的帳號,可如下例:

例:
$ cat /etc/passwd | grep '/home' | cut -d: -f1 | sort
aaa
bbb
john
austin

^ back on top ^

重定向(redirections)
〝Redirection〞中文有有人譯為〝轉向〞、〝導向〞、〝重新導向〞、〝重導向〞或〝重定向〞,

管線中有稍為介紹說:「Linux 的標準輸入(stdin)為鍵盤,標準輸出(stdout)為螢幕」。
更詳細一點如下表,標準輸入 stdin 的 fd 為 0。經指令或程式處理後,如可正常處理所產生在螢幕的訊息為標準輸出 stdout (fd 1)。如處理有誤也會有錯誤輸出到螢幕即 stderr(fd 2)。
輸入   程式   輸出
fd 0,stdin (standard input) programs fd 1,stdout (standard output)
fd 2,stderr (standard error)
但輸出/入的〝標準〞是可以改的,輸出輸入是可〝重定向〞(redirection) 的不一定是鍵盤或螢幕,舉例來說一個指令或程式的輸出原本是輸往螢幕,經〝重定向〞後可輸往檔案。

管線的符號只有〝|〞比較簡單,但〝重定向〞的符號因有 stdin (fd 0), stdout (fd 1) 和 stderr (fd 2),和累加重定向,所以組合複雜一些;下為可能的表示法和用法:

符號 動作
1> 或 > 標準輸出重定向,因標準輸出(stdout)的 File Descriptor 原本就是1,故〝1〞可省略
1>> 或 >> 標準輸出累加重定向
2> 錯誤輸出(stderr)重定向
2>> 錯誤輸出累加重定向
0< 或 < 標準輸入重定向,因標準輸入(stdin) 的 fd 原本就是0,故〝0〞可省略
- 標準輸入
2>&1 stderr 重定向 stdout
1>&2 或 >&2 stdout 重定向 stderr
<< STRING 結束的輸入字串

有些重定向功能有點抽象,一一來說明:

^ back on top ^

tee T型管線
〝1>〞或〝>〞標準輸出重定向可把原輸往螢幕輸往檔案(或裝置檔),但如果想同時要輸往螢幕又要輸往檔案怎麼辦呢?就在管線中再加一分流管線成〝T型管線〞即可。
〝T型管線〞指令 tee 的動作如下圖,接個分流管把檔案分流出來:

Linux tee pipe
T型管線 tee 用法如下:

語法: read_from_stdout | tee [-otpiton] file
指令名稱/功能/命令使用者 選項 功能
tee/
(pipe tee) T型管線/
Any
-a 輸出累加重定向
-i 忽略中斷

例:
$ echo 'Hello World' | tee tee_file.txt ←把原只輸出到螢幕用T型管線 tee 同時分流向檔案(螢幕和檔案都有輸出)
Hello World ←螢幕的輸出
$ cat tee_file.txt ←驗證一下用 tee 分流出來的檔案
Hello World

例:
$ man tee | tee -a file1 file2 file3 ←tee 可一次分流出多個檔案


^ back on top ^


 


1.1 指令傳回值與指令執行流程

Linux 99% 以上用 C 語言寫的,而 C 語言有一特色就是程式結束時會傳回一值給系統。其間的共識是如程式執行無誤傳回值為 0。如非 0 表示程式執行時遇到狀況。

其傳回值有兩個功用,其一讓可知錯誤的原因 (非 0 的傳回值可查表或由 manpage 得知可能的錯誤原因)其二是給腳本語言(Script Laguage)作流程的判斷。

那如何知道指令的傳回值?在文字介面下輸入 echo $? 即可知上個指令的傳回值。

例: (以一般使用者的帳號登入測試)
$ cd ~root ←進入 root 的家目錄
bash: cd: /root: Permission denied ←許可拒絕 (有錯誤產生)
$ echo $? ←查看剛的指令傳回值
1 ←非 0 表示程式執行有誤
$ cd ~ ←進入自己的家目錄
$ echo $? ←查看剛的指令傳回值
0 ←為 0 表示程式執行正確

^ back on top ^

〝&&〞傳回值為 0 執行
當〝&&〞前面指令執行無誤(傳回值為 0時)則〝&&〞後面的指令會被執行,如否則否,時常用於腳本語言的判斷式。

基本的用法為 CMD1 && CMD2 && CMD3 && ... && CMDn,其規則是:由左自右,如指令執行結果無誤(執令傳回值為 0)即可穿越〝&&〞執行下一個指令;如執行結果有誤,會被〝&&〞擋住不執行。(其實還蠻好記的,符號〝&&〞都是洞洞,故傳回值為 0 可穿越而執行下一個指令)。

例:
# cd /root && mv /root/fileA /root/fileB && clear ←如執行〝cd〞無誤則再執行〝mv〞如再如誤誤則執行〝clear〞

〝||〞傳回值為 ≠0 執行
和〝&&〞相反,〝||〞為執行結果傳回值 ≠0 (執行結果不太正常)才執行後面的指令。

例:
$ cat /etc/man.conf || cat /etc/man.config ←如〝cat /etc/man.conf〞 有誤則執行〝cat /etc/man.config〞

〝&&〞和〝||〞可混搭使用。
例:
$ [ -f fileA ] && [ -f fileB ] && echo "exist" || echo "Not found" ←如第一個指令結果不正常〝&&〞後的指令都不會被執行而是執行〝||〞後面的指令


^ back on top ^