【重定向】linux的重定向總結


轉載自:http://c.biancheng.net/view/5956.html  

  我們知道,Linux 中標准的輸入設備默認指的是鍵盤,標准的輸出設備默認指的是顯示器。而本節所要介紹的輸入、輸出重定向,完全可以從字面意思去理解,也就是:

  • 輸入重定向:指的是重新指定設備來代替鍵盤作為新的輸入設備;
  • 輸出重定向:指的是重新指定設備來代替顯示器作為新的輸出設備。

通常是用文件或命令的執行結果來代替鍵盤作為新的輸入設備,

Linux輸入重定向

對於輸入重定向來說,其需要用到的符號以及作用如表 1 所示。

表 1 輸入重定向中用到的符號及作用
命令符號格式 作用
命令 < 文件 將指定文件作為命令的輸入設備
命令 << 分界符 表示從標准輸入設備(鍵盤)中讀入,直到遇到分界符才停止(讀入的數據不包括分界符),這里的分界符其實就是自定義的字符串
命令 < 文件 1 > 文件 2 將文件 1 作為命令的輸入設備,該命令的執行結果輸出到文件 2 中。

而新的輸出設備通常指的就是文件。

Linux重定向的介紹

就像我們平時寫的程序一樣,一段程序會處理外部的輸入,然后將運算結果輸出到指定的位置。在交互式的程序中,輸入來自用戶的鍵盤和鼠標,結果輸出到用戶的屏幕,甚至播放設備中。而對於某些后台運行的程序,輸入可能來自於外部的一些文件,運算的結果通常又寫到其他的文件中。而且程序在運行的過程中,會有一些關鍵性的信息,比如異常堆棧,外部接口調用情況等,這些都會統統寫到日志文件里。

shell腳本也一樣,但是我們一般在使用shell命令的時候,更多地還是通過鍵盤輸入,然后在屏幕上查看命令的執行結果。如果某些情況下,我們需要將shell命令的執行結果存儲到文件中,那么我們就需要使用輸入輸出的重定向功能。

文件描述符

當執行shell命令時,會默認打開3個文件,每個文件有對應的文件描述符來方便我們使用:

 

類型 文件描述符 默認情況 對應文件句柄位置
標准輸入(standard input) 0 從鍵盤獲得輸入 /proc/self/fd/0
標准輸出(standard output) 1 輸出到屏幕(即控制台) /proc/self/fd/1
錯誤輸出(error output) 2 輸出到屏幕(即控制台) /proc/self/fd/2

 

所以我們平時在執行shell命令中,都默認是從鍵盤獲得輸入,並且將結果輸出到控制台上。但是我們可以通過更改文件描述符默認的指向,從而實現輸入輸出的重定向。比如我們將1指向文件,那么標准的輸出就會輸出到文件中。

【例 1】
默認情況下,cat 命令會接受標准輸入設備(鍵盤)的輸入,並顯示到控制台,但如果用文件代替鍵盤作為輸入設備,那么該命令會以指定的文件作為輸入設備,並將文件中的內容讀取並顯示到控制台。

以 /etc/passwd 文件(存儲了系統中所有用戶的基本信息)為例,執行如下命令:

[root@localhost ~]# cat /etc/passwd
#這里省略輸出信息,讀者可自行查看
[root@localhost ~]# cat < /etc/passwd
#輸出結果同上面命令相同

注意,雖然執行結果相同,但第一行代表是以鍵盤作為輸入設備,而第二行代碼是以 /etc/passwd 文件作為輸入設備。

【例 2】

[root@localhost ~]# cat << 0
>c.biancheng.net
>Linux
>0
c.biancheng.net
Linux

可以看到,當指定了 0 作為分界符之后,只要不輸入 0,就可以一直輸入數據。

【例 3】
首先,新建文本文件 a.tx,然后執行如下命令:

[root@localhost ~]# cat a.txt
[root@localhost ~]# cat < /etc/passwd > a.txt
[root@localhost ~]# cat a.txt
#輸出了和 /etc/passwd 文件內容相同的數據

可以看到,通過重定向 /etc/passwd 作為輸入設備,並輸出重定向到 a.txt,最終實現了將 /etc/passwd 文件中內容復制到 a.txt 中。

Linux輸出重定向

相較於輸入重定向,我們使用輸出重定向的頻率更高。並且,和輸入重定向不同的是,輸出重定向還可以細分為標准輸出重定向和錯誤輸出重定向兩種技術。

例如,使用 ls 命令分別查看兩個文件的屬性信息,但其中一個文件是不存在的,如下所示:

[root@localhost ~]# touch demo1.txt
[root@localhost ~]# ls -l demo1.txt
-rw-rw-r--. 1 root root 0 Oct 12 15:02 demo1.txt
[root@localhost ~]# ls -l demo2.txt    <-- 不存在的文件
ls: cannot access demo2.txt: No such file or directory

上述命令中,demo1.txt 是存在的,因此正確輸出了該文件的一些屬性信息,這也是該命令執行的標准輸出信息;而 demo2.txt 是不存在的,因此執行 ls 命令之后顯示的報錯信息,是該命令的錯誤輸出信息。

再次強調,要想把原本輸出到屏幕上的數據轉而寫入到文件中,這兩種輸出信息就要區別對待。

在此基礎上,標准輸出重定向和錯誤輸出重定向又分別包含清空寫入和追加寫入兩種模式。因此,對於輸出重定向來說,其需要用到的符號以及作用如表 2 所示。

表 2 輸出重定向用到的符號及作用
命令符號格式 作用
命令 > 文件 將命令執行的標准輸出結果重定向輸出到指定的文件中,如果該文件已包含數據,會清空原有數據,再寫入新數據。
命令 2> 文件 將命令執行的錯誤輸出結果重定向到指定的文件中,如果該文件中已包含數據,會清空原有數據,再寫入新數據。
命令 >> 文件 將命令執行的標准輸出結果重定向輸出到指定的文件中,如果該文件已包含數據,新數據將寫入到原有內容的后面。
命令 2>> 文件 將命令執行的錯誤輸出結果重定向到指定的文件中,如果該文件中已包含數據,新數據將寫入到原有內容的后面。
命令 >> 文件 2>&1
或者
命令 &>> 文件
將標准輸出或者錯誤輸出寫入到指定文件,如果該文件中已包含數據,新數據將寫入到原有內容的后面。注意,第一種格式中,最后的 2>&1 是一體的,可以認為是固定寫法。


【例 4】新建一個包含有 "Linux" 字符串的文本文件 Linux.txt,以及空文本文件 demo.txt,然后執行如下命令:

[root@localhost ~]# cat Linux.txt > demo.txt
[root@localhost ~]# cat demo.txt
Linux
[root@localhost ~]# cat Linux.txt > demo.txt
[root@localhost ~]# cat demo.txt
Linux     <--這里的 Linux 是清空原有的 Linux 之后,寫入的新的 Linux
[root@localhost ~]# cat Linux.txt >> demo.txt
[root@localhost ~]# cat demo.txt
Linux
Linux     <--以追加的方式,新數據寫入到原有數據之后
[root@localhost ~]# cat b.txt > demo.txt
cat: b.txt: No such file or directory  <-- 錯誤輸出信息依然輸出到了顯示器中
[root@localhost ~]# cat b.txt 2> demo.txt
[root@localhost ~]# cat demo.txt
cat: b.txt: No such file or directory  <--清空文件,再將錯誤輸出信息寫入到該文件中
[root@localhost ~]# cat b.txt 2>> demo.txt
[root@localhost ~]# cat demo.txt
cat: b.txt: No such file or directory
cat: b.txt: No such file or directory  <--追加寫入錯誤輸出信息

Linux重定向的一些高級用法

重定向綁定

關於/dev/null 2>&1,這條命令其實分為兩命令,一個是>/dev/null,另一個是2>&1

1. >/dev/null

這條命令的作用是將標准輸出1重定向到/dev/null中。 /dev/null代表linux的空設備文件,所有往這個文件里面寫入的內容都會丟失,俗稱“黑洞”。那么執行了>/dev/null之后,標准輸出就會不再存在,沒有任何地方能夠找到輸出的內容。

2. 2>&1

這條命令用到了重定向綁定,采用&可以將兩個輸出綁定在一起。這條命令的作用是錯誤輸出將和標准輸出同用一個文件描述符,說人話就是錯誤輸出將會和標准輸出輸出到同一個地方。

linux在執行shell命令之前,就會確定好所有的輸入輸出位置,並且從左到右依次執行重定向的命令,所以>/dev/null 2>&1的作用就是讓標准輸出重定向到/dev/null中(丟棄標准輸出),然后錯誤輸出由於重用了標准輸出的描述符,所以錯誤輸出也被定向到了/dev/null中,錯誤輸出同樣也被丟棄了。執行了這條命令之后,該條shell命令將不會輸出任何信息到控制台,也不會有任何信息輸出到文件中。

>/dev/null 2>&1 VS 2>&1 >/dev/null

再回到文章的開頭,我說我弄反了>/dev/null2>&1拼裝的順序,導致出了一點小問題。乍眼看這兩條命令貌似是等同的,但其實大為不同。剛才提到了,linux在執行shell命令之前,就會確定好所有的輸入輸出位置,並且從左到右依次執行重定向的命令。那么我們同樣從左到右地來分析2>&1 >/dev/null

2>&1,將錯誤輸出綁定到標准輸出上。由於此時的標准輸出是默認值,也就是輸出到屏幕,所以錯誤輸出會輸出到屏幕。
>/dev/null,將標准輸出1重定向到/dev/null中。

我們用一個表格來更好地說明這兩條命令的區別:

 

命令 標准輸出 錯誤輸出
>/dev/null 2>&1 丟棄 丟棄
2>&1 >/dev/null 丟棄 屏幕

 

>/dev/null 2>&1 VS >/dev/null 2>/dev/null

那么可能會有些同學會疑問,為什么要用重定向綁定,而不是像>/dev/null 2>/dev/null這樣子重復一遍呢。

為了回答這個問題,我們回到剛才介紹輸出重定向的場景。我們嘗試將標准輸出和錯誤輸出都定向到out文件中:

1
2
3
4
# ls a.txt b.txt >out 2>out
# cat out
a.txt
無法訪問b.txt: 沒有那個文件或目錄

WTF?竟然出現了亂碼,這是為啥呢?這是因為采用這種寫法,標准輸出和錯誤輸出會搶占往out文件的管道,所以可能會導致輸出內容的時候出現缺失、覆蓋等情況。現在是出現了亂碼,有時候也有可能出現只有error信息或者只有正常信息的情況。不管怎么說,采用這種寫法,最后的情況是無法預估的。

而且,由於out文件被打開了兩次,兩個文件描述符會搶占性的往文件中輸出內容,所以整體IO效率不如>/dev/null 2>&1來得高。

用途:

1. 不讓輸出任何信息到屏幕

就用:命令 > /dev/null 2>&1


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM