一文帶你簡(jiǎn)單理解linux中的輸入輸出重定向
linux簡(jiǎn)單理解輸入輸出重定向
linux重定向可以分為輸出重定向和輸入重定向。在系統(tǒng)中除了標(biāo)準(zhǔn)輸入、標(biāo)準(zhǔn)輸出、錯(cuò)誤輸出以外,其他的重定向,都需要指定文件描述符id,也可以稱為句柄。
在linux中,可以通過查看/proc/進(jìn)程pid號(hào)/fd/下的文件來查看該進(jìn)程有多少個(gè)fd,比如:
# ls -l /proc/$$/fd/ total 0 lrwx------. 1 root root 64 Jun 3 22:22 0 -> /dev/pts/0 lrwx------. 1 root root 64 Jun 3 22:22 1 -> /dev/pts/0 lrwx------. 1 root root 64 Jun 3 22:22 2 -> /dev/pts/0 #
上述命令中$$表示該進(jìn)程本身的pid,而該fd文件下,可以看到有0、1、2 三個(gè)文件,都指向/dev/pts/0,這是一個(gè)字符設(shè)備文件,表示當(dāng)前的終端。
輸出重定向原理
對(duì)于系統(tǒng)而言,任何一個(gè)程序都有2個(gè)輸出,分別是:
- 文件描述符為1的標(biāo)準(zhǔn)輸出
- 文件描述符為2的錯(cuò)誤輸出
所以,當(dāng)執(zhí)行一個(gè)命令輸出重定向的時(shí)候,比如:
command >> filename
上述命令是將command命令執(zhí)行的標(biāo)準(zhǔn)輸出結(jié)果重定向到filename文件中,你可以理解為在執(zhí)行該命令的時(shí)候,其進(jìn)程標(biāo)準(zhǔn)輸出文件描述符1由默認(rèn)的/dev/pts/0指向了filename文件,為此可以來寫一個(gè)程序來試試。
程序如下:
#!/bin/bash
echo "pid: $$" >&2
while true
do
echo 123
sleep 3
done
這個(gè)程序非常簡(jiǎn)單,首先現(xiàn)輸出該腳本的pid到錯(cuò)誤輸出上,即文件描述符為2,而后定一個(gè)無限循環(huán),每隔3秒輸出123。
在執(zhí)行的時(shí)候,將該文件輸出重定向到filename中。
# bash test.sh >> filename pid: 42699
程序執(zhí)行會(huì)卡主,這是正常的,這是因?yàn)橛袩o限循環(huán),每隔3秒會(huì)輸出123字符串至標(biāo)準(zhǔn)輸出上。
而后打開一個(gè)新的終端,查看42699的fd文件信息。
# ls -l /proc/42699/fd/ total 0 lrwx------. 1 root root 64 Jun 3 23:41 0 -> /dev/pts/0 l-wx------. 1 root root 64 Jun 3 23:41 1 -> /root/fd/filename lrwx------. 1 root root 64 Jun 3 23:41 2 -> /dev/pts/0 lr-x------. 1 root root 64 Jun 3 23:41 255 -> /root/fd/test.sh #
通過上面執(zhí)行的結(jié)果可以發(fā)現(xiàn),其標(biāo)準(zhǔn)輸出,文件描述符為1已經(jīng)指向一個(gè)文件:/root/fd/filename,而非終端字符設(shè)備。所以說,在上面案例中,重定向后,實(shí)際上是將句柄給改寫到文件中,所以屏幕沒有輸出任何數(shù)據(jù)?;诖耍瑯?biāo)準(zhǔn)輸入和錯(cuò)誤輸出的原理也是這樣的。
輸出重定向
輸出重定向一般格式為:[n]>[|]filename,其中n是文件描述符,>|表示覆蓋保護(hù)繞過機(jī)制,不過一般不用,即常用的寫法為:[n]>filename。
比如,將字符串abcdef的標(biāo)準(zhǔn)輸出重定向到filename中:
echo "abcdef" 1> filename
默認(rèn)情況下,1>可以縮略寫為>,這也是常用的寫法:
echo "abcde" > filename
將命令dasdsada的錯(cuò)誤結(jié)果寫入到文件filename中:
dasdsada 2> filename
因?yàn)闆]有這個(gè)命令,所以一定會(huì)報(bào)錯(cuò)-bash: dasdsada: command not found。
對(duì)于該重定向而言,它在執(zhí)行前會(huì)清理掉原始內(nèi)容,從而寫入新的內(nèi)容。
除此之外,還有追加重定向,其格式為[n]>>filename,其中n是文件描述符,>>表示追加,它不會(huì)清理掉原有內(nèi)容。比如將abc追加到文件filename中。
echo 123 1>> filename
同樣的,也可以將1>>縮略寫為>>。
將命令aaa的錯(cuò)誤結(jié)果追加寫入到文件filename中:
aaa 2>> filename
輸入重定向
在linux系統(tǒng)中,任何一個(gè)程序的標(biāo)準(zhǔn)輸入文件描述符id為0,而輸入重定向一般格式為[n]<filename,其中n表示文件描述符。
所以,如下命令:
cat 0< filename
它的意思是將filename文件的內(nèi)容作為標(biāo)準(zhǔn)輸入提供給cat調(diào)用,結(jié)果是打印了filename的內(nèi)容,上述命令中的0<可以縮略寫為<。
不僅如此,還能在循環(huán)中,搭配read,將文件的信息按行讀取。
比如有以下文件內(nèi)容:
# cat filename aa bb cc dd #
有腳本內(nèi)容如下:
#!/bin/bash
while read ll
do
echo read_at: ${ll}
done 0< filename
上述腳本表示將filename文件作為輸入源,供while調(diào)用,按照的方式是read命令按行調(diào)用,將行內(nèi)容賦值到ll變量上,這個(gè)變量名稱可以自定義。
其結(jié)果為:
# bash test.sh read_at: aa read_at: bb read_at: cc read_at: dd #
輸入重定向還有一種表達(dá)方式是here-documents。表示多行定義輸入,其語法為:
command [n]<<word here doc word
其中n表示文件操作符,如果省略,則使用默認(rèn)的文件操作符0,而后是關(guān)鍵字<<,word是自定義的結(jié)束符,讓后續(xù)讀取到word后停止讀取。
比如:
cat <<END 123 456 789 END
輸出的結(jié)果為
123
456
789
上述命令中的END是可以替換為任何字符串的,只要后續(xù)出現(xiàn)該字符串就會(huì)停止輸入,注意這個(gè)字符,一定是要在單獨(dú)的一行出現(xiàn)的,不能有其他字符,包括空格。
here-documents會(huì)進(jìn)行命令替換,變量替換等,比如有如下命令:
# x=123
# cat <<END
${x}
$(pwd)
aa
bb
cc
END
輸出的結(jié)果會(huì)先進(jìn)行命令替換,變量替換等,比如將${x}替換為123,將$(pwd)替換為當(dāng)前目錄。如果不想其被替換,則需要添加單引號(hào)進(jìn)行轉(zhuǎn)義。
重定向的順序
注意看,如下有2條命令:
ls -l > filename 2>&1
和
ls -l 2>&1 > filename
所執(zhí)行的結(jié)果是完全不一樣的,第一條命令是將標(biāo)準(zhǔn)輸出和錯(cuò)誤輸出都寫入到filename中,而第二條則是將錯(cuò)誤輸出輸出到屏幕上,而將標(biāo)準(zhǔn)輸出寫入到文件中,如果不是很明白,可以嘗試拆解一下命令:
首先,命令的前提是:標(biāo)準(zhǔn)輸出 和 錯(cuò)誤輸出 都在某個(gè)設(shè)備上,比如pty終端,假設(shè)設(shè)備為/dev/pts/0,所以文件描述符信息為:
1 -> /dev/pts/02 -> /dev/pts/0
然后第一條命令,ls -l > filename 其實(shí)是將文件描述符1給指向了文件filename,這個(gè)時(shí)候,文件描述符信息為:
1 -> filename2 -> /dev/pts/0
這個(gè)時(shí)候再使用2>&1表示將錯(cuò)誤消息也寫入到文件描述符為1的文件中,即filename,所以最后的文件描述符為:
1 -> filename2 -> filename
而第二條命令,一開始都是輸出到某個(gè)設(shè)備上:
1 -> /dev/pts/02 -> /dev/pts/0
這個(gè)時(shí)候,它將錯(cuò)誤輸出指向2>&1,而文件描述符為1是/dev/pts/0,所以這第一步,就沒動(dòng)過,而第二部則是將標(biāo)準(zhǔn)輸出指向filename,即:
1 -> filename2 -> /dev/pts/0
所以第二條命令,錯(cuò)誤輸出輸出到屏幕上,而將標(biāo)準(zhǔn)輸出寫入到文件中。
總結(jié)
要理解輸入輸出重定向,一定要理解文件的描述符!對(duì)于每個(gè)進(jìn)程,都會(huì)產(chǎn)生3個(gè)默認(rèn)的文件描述符,分別是 標(biāo)準(zhǔn)輸入、標(biāo)準(zhǔn)輸出 和 錯(cuò)誤輸出,用文件描述符id:0、1、2 來表示。
其重定向就是修改這些文件描述符的指向,將他們指向到文件中即可。
對(duì)于輸入重定向而言,有一種表達(dá)方式是here-documents,它可以和輸出重定向結(jié)合,將終端中輸入的文件寫入到文件中,比如:
cat 1>> filename 0<<END a b c d e END
表示將終端輸入的a、b... e字符提供給cat命令,而cat將內(nèi)容重定向到文件filename中??梢园l(fā)現(xiàn)上面有1>>表示將標(biāo)準(zhǔn)輸出的內(nèi)容重定向到某個(gè)文件,0<<表示將標(biāo)準(zhǔn)輸入的內(nèi)容重定向到某個(gè)文件,上述命令中的1>>可以縮寫為>>,而0<<可以縮寫為<<。
到此這篇關(guān)于一文帶你簡(jiǎn)單理解linux中的輸入輸出重定向的文章就介紹到這了,更多相關(guān)linux輸入輸出重定向內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
mac 安裝omyzsh后不執(zhí)行~/.bash_profile、~/.bashrc的完美解決辦法
mac 安裝 omyzsh 后, terminal瞬間格調(diào)飆升,但是,terminal init的時(shí)候并不會(huì)執(zhí)行~/.bash_profile、~/.bashrc等腳本了,什么原因呢?下面小編給大家分享解決辦法,一起看看吧2017-01-01
Linux中自定義shell腳本啟動(dòng)jar包的方法
這篇文章主要介紹了Linux中自定義shell腳本啟動(dòng)jar包的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-01-01
Shell $?獲取函數(shù)返回值或者上一個(gè)命令的退出狀態(tài)
這篇文章主要介紹了Shell $?獲取函數(shù)返回值或者上一個(gè)命令的退出狀態(tài),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01
Linux 使用grep篩選多個(gè)條件及grep常用過濾命令
這篇文章主要介紹了Linux 使用grep篩選多個(gè)條件及grep常用過濾命令,需要的朋友可以參考下2018-07-07
linux下批量刪除utf8 bom的實(shí)現(xiàn)方法
下面小編就為大家?guī)硪黄猯inux下批量刪除utf8 bom的實(shí)現(xiàn)方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-03-03

