首頁 > 軟體

Linux 基礎入門教學----資料流重定向

2020-06-16 17:55:35

介紹

開始對重定向這個概念感到些許陌生,但通過前面的課程中多次見過>>>操作了,並知道他們分別是將標準輸出導向一個檔案或追加到一個檔案中。這其實就是重定向,將原本輸出到標準輸出的資料重定向到一個檔案中,因為標準輸出(/dev/stdout)本身也是一個檔案,我們將命令輸出導向另一個檔案自然也是沒有任何問題的。

一、資料流重定向

下面簡單的回顧一下前面經常用到的兩個重定向操作:

$ echo 'hello shiyanlou' > redirect 
$ echo 'www.shiyanlou.com' >> redirect
$ cat redirect

當然前面沒有用到的<<<操作也是沒有問題的,如你理解的一樣,它們的區別在於重定向的方向不一致而已,>表示是從左到右,<右到左。

1.簡單的重定向

在更多了解 Linux 的重定向之前,需要先知道一些基本的東西,前面已經提到過 Linux 預設提供了三個特殊裝置,用於終端的顯示和輸出,分別為stdin(標準輸入,對應於你在終端的輸入),stdout(標準輸出,對應於終端的輸出),stderr(標準錯誤輸出,對應於終端的輸出)。

檔案描述符裝置檔案說明
0 /dev/stdin 標準輸入
1 /dev/stdout 標準輸出
2 /dev/stderr 標準錯誤

檔案描述符:檔案描述符在形式上是一個非負整數。實際上,它是一個索引值,指向核心為每一個進程所維護的該進程開啟檔案的記錄表。當程式開啟一個現有檔案或者建立一個新檔案時,核心向進程返回一個檔案描述符。在程式設計中,一些涉及底層的程式編寫往往會圍繞著檔案描述符展開。但是檔案描述符這一概念往往只適用於 UNIX、Linux 這樣的作業系統。

另外還有一個符號-,它可以同時作為前一個命令的。

可以這樣使用這些檔案描述符:

預設使用終端的標準輸入作為命令的輸入和標準輸出作為命令的輸出

$ cat 
(按Ctrl+C退出)

將cat的連續輸出(heredoc方式)重定向到一個檔案

$ mkdir Documents
$ cat > Documents/test.c~ <<EOF
#include <stdio.h>

int main()
{
    printf("hello worldn");
    return 0;
}

EOF

將一個檔案作為命令的輸入,標準輸出作為命令的輸出

$ cat Documents/test.c~

將echo命令通過管道傳過來的資料作為cat命令的輸入,將標準輸出作為命令的輸出

$ echo 'hi' | cat

將echo命令的輸出從預設的標準輸出重定向到一個普通檔案

$ echo 'hello shiyanlou' > redirect
$ cat redirect

注意不要將管道和重定向混淆,管道預設是連線前一個命令的輸出到下一個命令的輸入,而重定向通常是需要一個檔案來建立兩個命令的連線,仔細體會一下上述第三個操作和最後兩個操作的異同點。

2.標準錯誤重定向

重定向標準輸出到檔案,這是一個很實用的操作,另一個很實用的操作是將標準錯誤重定向,標準輸出和標準錯誤都被指向偽終端的螢幕顯示,所以經常看到的一個命令的輸出通常是同時包含了標準輸出和標準錯誤的結果的。比如下面的操作:

# 使用cat 命令同時讀取兩個檔案,其中一個存在,另一個不存在
$ cat Documents/test.c~ hello.c
# 你可以看到除了正確輸出了前一個檔案的內容,還在末尾出現了一條錯誤資訊
# 下面我們將輸出重定向到一個檔案,根據我們前面的經驗,這裡將在看不到任何輸出了
$ cat Documents/test.c~ hello.c > somefile

遺憾的是,這裡依然出現了那條錯誤資訊,這正是因為如我上面說的那樣,標準輸出和標準錯誤雖然都指向終端螢幕,實際它們並不一樣。那有的時候我們就是要可以隱藏某些錯誤或者警告,那又該怎麼做呢。這就需要用到前面講的檔案描述符了:

# 將標準錯誤重定向到標準輸出,再將標準輸出重定向到檔案,注意要將重定向到檔案寫到前面
$ cat Documents/test.c~ hello.c >somefile  2>&1
# 或者只用bash提供的特殊的重定向符號"&"將標準錯誤和標準輸出同時重定向到檔案
$ cat Documents/test.c~ hello.c &>somefilehell

注意你應該在輸出重定向檔案描述符前加上&,否則shell會當做重定向到一個檔名為1的檔案中

3.使用tee命令同時重定向到多個檔案

經常你可能還有這樣的需求,除了將需要將輸出重定向到檔案之外也需要將資訊列印在終端,那麼你可以使用tee命令來實現:

$ echo 'hello shiyanlou' | tee hello

4.永久重定向

你應該可以看出我們前面的重定向操作都只是臨時性的,即只對當前命令有效,那如何做到“永久”有效呢,比如在一個指令碼中,你需要某一部分的命令的輸出全部進行重定向,難道要讓你在每個命令上面加上臨時重定向的操作嘛,當然不需要,我們可以使用exec命令實現“永久”重定向。exec命令的作用是使用指定的命令替換當前的 Shell,及使用一個進程替換當前進程,或者指定新的重定向:

# 先開啟一個子 Shell
$ zsh
# 使用exec替換當前進程的重定向,將標準輸出重定向到一個檔案
$ exec 1>somefile
# 後面你執行的命令的輸出都將被重定向到檔案中,直到你退出當前子shell,或取消exec的重定向(後面將告訴你怎麼做)
$ ls
$ exit
$ cat somefile

5.建立輸出檔案描述符

預設在 Shell 中可以有9個開啟的檔案描述符,上面我們使用了也是它預設提供的0,1,2號檔案描述符,另外我們還可以使用3-8的檔案描述符,只是它們預設沒有開啟而已,你可以使用下面命令檢視當前 Shell 進程中開啟的檔案描述符:

$ cd /dev/fd/;ls -Al

同樣使用exec命令可以建立新的檔案描述符:

$ zsh
$ exec 3>somefile
# 先進入目錄,再檢視,否則你可能不能得到正確的結果,然後再回到上一次的目錄
$ cd /dev/fd/;ls -Al;cd -
# 注意下面的命令>與&之間不應該有空格,如果有空格則會出錯
$ echo "this is test" >&3
$ cat somefile
$ exit

6.關閉檔案描述符

如上面我們開啟的3號檔案描述符,可以使用如下操作將它關閉:

$ exec 3>&-
$ cd /dev/fd;ls -Al;cd -

7.完全螢幕蔽命令的輸出

在 Linux 中有一個被成為“黑洞”的裝置檔案,所以匯入它的資料都將被“吞噬”。

在類 UNIX 系統中,/dev/null,或稱空裝置,是一個特殊的裝置檔案,它通常被用於丟棄不需要的輸出流,或作為用於輸入流的空檔案,這些操作通常由重定向完成。讀取它則會立即得到一個EOF。

我們可以利用設個/dev/null遮蔽命令的輸出:

$ cat Documents/test.c~ nefile 1>/dev/null 2>&1

向上面這樣的操作將使你得不到任何輸出結果。

8.使用 xargs 分割參數列

xargs 是一條 UNIX 和類 UNIX 作業系統的常用命令。它的作用是將參數列轉換成小塊分段傳遞給其他命令,以避免參數列過長的問題。

這個命令在有些時候十分有用,特別是當用來處理產生大量輸出結果的命令如 find,locate 和 grep 的結果,詳細用法請參看 man 文件。

$ cut -d: -f1 < /etc/passwd | sort | xargs echo

上面這個命令用於將/etc/passwd檔案按:分割取第一個欄位排序後,使用echo命令生成一個列表。

本文永久更新連結地址http://www.linuxidc.com/Linux/2015-08/121442.htm


IT145.com E-mail:sddin#qq.com