這一篇講一下重定向shell
有些時候你想要保存某些命令產生的輸出而不是在顯示器上顯示它。
爲了應對這樣的問題 bash shell 也就提供了一些重定向的操做符。
咱們先了解一些基本的應用。bash
輸出重定向
輸出重定向最基本的就是將命令的輸出重定向到文件中,bash shell 採用了( > ) 這個符號來實現這個功能。
command > outputfile
這樣本應該在顯示器上顯示的內容就保存在了文件中。
命令行#!/bin/bash
today=`date +%y%m%d`
echo $today
ls -al > log.$today
$ ./shell5
171108
$
$ cat log.171108
-rw-rw-r--. 1 forever forever 0 11月 8 19:44 log.171108
-rwxrw-r--. 1 forever forever 84 11月 8 17:21 shell1
-rwxrw-r--. 1 forever forever 45 11月 8 18:25 shell2
-rwxrw-r--. 1 forever forever 187 11月 8 18:42 shell3
-rwxrw-r--. 1 forever forever 50 11月 8 18:52 shell4
-rwxrw-r--. 1 forever forever 66 11月 8 19:44 shell5
......
$
這樣就將命令的輸出重定向到了log.$today中,log.$today這也是日誌文件獲取時間的一種方式。
( > )使用的時候就會將原有文件覆蓋。可是有的時候你並不想這麼作,那麼就可使用( >> )來追加數據。
輸入重定向
輸入重定向正好和輸出重定向相反。輸入重定向將文件的內容重定向到命令,
bash shell 採用了( < )這個符號來實現這個功能。
command < inputfile
無論輸入重定向仍是輸出重定向,這個大於號和小於號都十分的形象,都是將數據從一邊流向另外一邊,這樣就不會記錯了。
指針$ bc < text1
3
$
一樣輸入重定向也有另外一種方式,叫作 內聯輸入重定向( << )這樣是能夠從命令行輸入數據,使用的方式是這樣的。
command << marker
data
marker
$ bc << EOF
1+2
EOF
3
$
管道
有的時候你須要將一個命令的輸出,做爲另外一個命令的輸入,這樣也能夠用重定向來解決這個問題,
將一個命令的輸出重定向到一個文件,再將文件重定向做爲另外一個命令的輸入,
可是我想你可能不會喜歡這麼作,這顯得很笨拙。
因此就有了管道( | )這個命令,
command1 | command2
管道的連接並非一個一個地運行,實際上它們是同時運行這兩個命令的,在系統內部將它們鏈接起來。在第一個命令產生輸出的同時,輸出會當即送給第二個命令,傳輸數據不會用到任何中間文件或緩衝區。日誌
理解輸入輸出
有的時候你可能並非想將數據的全部內容都顯示在顯示器上,有的你可能想保存在文本中,有的顯示在顯示器上,有的丟棄掉不要。
那麼下面我門就瞭解一下這方面的內容。code
文件描述符
在Linux系統中每一個對象都是看成文件來處理的,這之中就有輸入和輸出的過程,那麼就用文件描述符來標識每一個文件對象。
文件描述符標識着對應的文件,每一個過程當中最多可使用9個標識符,分別是( 0~8 ) 9個文件描述符。
bash shell 保留了( 0, 1, 2 )這三個文件描述符,其他的( 3~8 )的文件標識符用戶能夠自行定義使用。
( 0 )標識STDIN 標準輸入
( 1 )標識STDOUT 標準輸出
( 2 )標識STDERR 標準錯誤對象
STDIN表明的是標準輸入,輸入能夠來自不少方面,對於你如今使用的電腦最多見的應該就是鍵盤。input
STDOUT表明的是標準輸出,如今你若是在使用終端,那麼輸出的就是顯示器上,
那麼這個輸出也是能夠被重定向的,可能輸出到某個文件中。date
STDERR這個就是標準錯誤,若是你將一個命令重定向到一個文件,
若是結果正確了,的確不會有任何輸出,可是若是出現了錯誤提示,那麼你會發現它仍是顯示在了屏幕上。
file$ kkqaz > text1
bash: kkqaz: 未找到命令...
$
這個時候咱們已經將文件的輸出重定向到了text1中,kkqaz顯然不是一個命令,
這個時候它提示bash: kkqaz: 未找到命令...
,這段信息並無被重定向,
這就是由於,shell是經過特殊的文件標識符來處理錯誤信息的,
這就是STDERR,雖然STDOUT和STDERR都指向相同的地方,都會將他們的內容輸入到顯示器上。
可是當你使用 ( > )將STDOUT重定向的時候,STDERR並不會也跟着一個被重定向。
錯誤重定向
那麼應該如何解決這個問題?其實只要在前面加上文件標識符就能夠了。
$ kkqaz 2> text1
$ cat text1
bash: kkqaz: 未找到命令...
$
不過要注意的是文件標識符要緊挨着( > )否則就會出錯。
那麼若是你想將STDOUT和STDERR都重定向到文件中應該怎麼辦,其實只要使用兩個重定向就能夠實現。
$ ls -l text1 abc 1>text2 2>text3
$ cat text2
-rw-rw-r--. 1 forever forever 32 11月 9 13:21 text1
$ cat text3
ls: 沒法訪問abc: 沒有那個文件或目錄
$
這樣就能夠將信息和錯誤信息都輸入到了文件中,而且將他們分開了。
同時若是你想將信息和錯誤信息,都輸入到一個文件中,那也是能夠的。
你只要使用 &>就能夠將輸出和錯誤信息都輸出到同一個文件中。
$ ls -l text1 abc def &>text2
$ cat text2
ls: 沒法訪問abc: 沒有那個文件或目錄
ls: 沒法訪問def: 沒有那個文件或目錄
-rw-rw-r--. 1 forever forever 0 11月 9 13:38 text1
$
從文件中你能夠看出在重定向時,輸出的結果並非按照你預期的順序輸出的,
而是錯誤信息的的優先級更高一些,這樣就井井有理了。
也方便了你能夠到一個地方去尋找信息。
在腳本中時使用重定向
剛纔已經熟悉了在命令行中進行重定向,那麼接下來就來了解一下在腳本應如何使用吧。
在腳本中的重定向就分爲以下兩種:
1、臨時重定向。
2、永久重定向。
臨時重定向
當你向在腳本中輸出一段錯誤提示的時候,你就能夠這麼作。
echo "error data" >&2
若是你熟悉C語言的指針,我想這種形式對你來講會比較友好,也更容易理解。
$ cat shell6
#!/bin/bash
echo "This is an error" >&2
echo "This is output"
$./shell6
This is an error
This is output
$
兩句話都輸出了,好像看不出什麼不一樣,換個方式試試看。
$ ./shell6 1>text1
This is an error
$ ./shell6 2>text1
This is output
$
看起來不錯你的錯誤信息和正常輸出已經被區分出來了。
永久重定向
若是腳本中只有少許的輸出,使用臨時重定向的確是不錯的辦法,
可是當腳本中有大量的輸出的時候,在每一句輸出後都進行重定向那就太麻煩了。
那麼就可使用exec命令來告訴執行期間重定向到某個特定的文件描述符。
$ cat shell6
#!/bin/bash
exec 1>text2
echo "This is output"
$ ./shell6
$ cat text2
This is output
$
腳本中重定向輸入
咱們能夠將輸出重定向到其餘位置,那麼咱們也能夠將STDIN從鍵盤重定向到其餘位置。
最開始i重定向輸出的方法在這裏仍是可使用的。
固然仍是可使用exec命令的。
exec 0< inputfile
這個命令執行後,全部的輸入都會從inputfile文件中讀取。
$ cat inputtext
This is the first line
This is the second line
This is the third line
$ cat shell7
#!/bin/bash
exec 0< inputtext
count=1
while read line
do
echo "$count: $line"
count=$[ $count + 1 ]
done
$ ./shell7
This is the first line
This is the second line
This is the third line
$
這裏當read想要讀取用戶從鍵盤輸入的信息的時候就會從inputtext中讀取數據。
若是你要處理讀取文件的時候這就是一個絕佳的辦法。
本身的重定向
系統默認的只有三個文件描述符,可是有的時候三個標準文件描述符並非很夠用。
不過不用擔憂,還記得前面提過還有其餘6個文件描述符,那些文件描述符你均可以在腳本中給他們進行定義。
本身的文件描述符
咱們仍是可使用exec命令定義文件描述符
exec 3>text
$ cat shell8
#!/bin/bash
exec 3> text1
echo "This is the first one" >&3
exec 3>text2
echo "This is the second one" >&3
$ ./shell8
$ cat text1
This is the first one
$ cat text2
This is the second one
$
結果果真如你所向的那樣,重定向的內容都輸入到了相應的文件呢中,並無顯示在顯示在顯示器上。
重定向文件描述符
在你重定向標準文件描述符,若是你想再恢復原來所指向的地方,你發現不知道應該重定向到哪裏了。
下面就說一說如何將重定向的文件描述符恢復。
咱們將STDOUT重定向到了文件outputfile,當將部分輸出到了文件中後,咱們還有部分的想要顯示到屏幕的時候,這個時候咱們發現缺乏一個重定向的位置用來恢復。
那麼這個時候咱們就一個普通的文件描述符重定向到STDOUT,而後再將STDOUT重定向,在STDOUT的重定向使用完畢後,咱們再用普通的文件描述符,來讓STDOUT重定向到原來指向的位置。
下面仍是看一下實例吧。
$ cat shell9
#!bin/bash
exec 3>&1
exec 1>outputfile
echo "This will export to outputfile"
exec 1>&3
echo "This will output to display"
$ ./shell9
This will output to display
$ cat outputfile
This will export to outputfile
$
最開始咱們將文件描述符3重定向到了STDOUT,這樣3就保存了原來的STDOUT所指向的位置,方便以後能夠恢復。
隨後將STDOUT重定向到了outputfile文件,這樣在這個腳本中接下來的標準輸出都是輸出到了文件中。
在使用完這個後咱們將標準輸出,有重定向到了原來STDOUT所指向的位置,也是如今的文件描述符3,因此將STDOUT重定向到3所指向的位置。
這樣STDOUT的有將信息輸出到了顯示器上。
固然你使用這種方法的時候,固然沒有必要像前面這樣只有不多的輸出的時候使用了,exec命令也是要在有大量的信息,都要輸出到一樣的位置的時候使用這個命令就很划算了。
讀寫文件描述符
咱們還能夠用一個文件描述符,來進行對一個文件的輸入和輸出。
可是因爲這個文件描述符是一個單獨的對象,因此不論是讀或者寫,都會從上次執行結束的位置開始。
因此有的時候結果可能怪怪的。
$ cat shell10
#!/bin/bash
exec 3<>text3
read line <&3
echo "Hello" >&3
$ cat text3
This is a first text
This is a second text
This is a third text
$ ./shell10
$ cat text3
This is a first text
Hello
s a second text
This is a third text
$
關閉文件描述符
若是你再也不想使用一個文件描述符,那麼就咱們這裏給你提供一種方法。
exec 3>&-
這樣就會關閉文件描述符3,那麼若是你再使用就會出現錯誤。
最後咱們說一下,有的時候你不想將命令產生的一些如錯誤信息的輸出,也不想保存在任何地方。
這樣咱們能夠將輸出重定向到/dev/null中,這樣你不想要的信息就不會在任何地方出現了。
$ ls > /dev/null $ cat /dev/null $/dev/null文件就像他的文件名同樣什麼也沒有。 一樣你還能夠用經過將/dev/null文件中的內容重定向到文件中,來實現清空文件。