本文整理并轉(zhuǎn)自CU上的帖子[學(xué)習(xí)共享] shell 十三問 ?,此貼是2003年發(fā)表的,但卻是相當(dāng)不錯(cuò)的linux基礎(chǔ)知識(shí)匯集貼,原帖主使用的臺(tái)灣風(fēng)格,本文加以簡體化和整理。 第11問:> 與 < 差在哪?11.1談到I/O redirection ,不妨先讓我們認(rèn)識(shí)一下File Descriptor (FD)。程序的運(yùn)算,在大部份情況下都是進(jìn)行數(shù)據(jù)(data)的處理,這些數(shù)據(jù)從哪讀進(jìn)?又,送出到哪里呢?這就是File descriptor(FD)的功用了。 在shell程序中,最常使用的FD大概有三個(gè),分別為: - 0: Standard Input(STDIN)
- 1: Standard Output(STDOUT)
- 2: Standard Error Output(STDERR)
在標(biāo)準(zhǔn)情況下,這些FD分別跟如下設(shè)備(device)關(guān)聯(lián): - stdin(0):keyboard
- stdout(1):monitor
- stderr(2):monitor
我們可以用如下下命令測試一下: $ mail -s test root
this is a test mail.
please skip.
^d(同時(shí)按crtl跟d鍵)
很明顯,mail程序所讀進(jìn)的數(shù)據(jù),就是從stdin 也就是keyboard讀進(jìn)的。不過,不見得每個(gè)程序的stdin都跟mail一樣從keyboard讀進(jìn),因?yàn)槌绦蜃髡呖梢詮臋n案參數(shù)讀進(jìn)stdin,如: $ cat /etc/passwd
但,要是cat之后沒有檔案參數(shù)則又如何呢?哦,請您自己玩玩看啰….^_^ $ cat
(請留意數(shù)據(jù)輸出到哪里去了,最后別忘了按^d離開…)至于stdout與stderr,嗯…等我有空再續(xù)吧…^_^ 還是,有哪位前輩要來玩接龍呢? 11.2沿文再續(xù),書接上一回…^_^ 相信,經(jīng)過上一個(gè)練習(xí)后,你對stdin與stdout應(yīng)該不難理解吧?然后,讓我們繼續(xù)看stderr好了。 事實(shí)上,stderr沒甚么難理解的:說穿了就是“錯(cuò)誤信息”要往哪邊送而已…比方說,若讀進(jìn)的檔案參數(shù)是不存在的,那我們在monitor上就看到了: $ ls no.such.file
ls: no.such.file: No such file or directory
若,一個(gè)命令同時(shí)產(chǎn)生stdout與stderr呢?那還不簡單,都送到monitor來就好了: $ touch my.file
$ ls my.file no.such.file
ls: no.such.file: No such file or directory
my.file
okay,至此,關(guān)于FD及其名稱、還有相關(guān)聯(lián)的設(shè)備,相信你已經(jīng)沒問題了吧?那好,接下來讓我們看看如何改變這些FD的預(yù)設(shè)數(shù)據(jù)信道,我們可用<來改變讀進(jìn)的數(shù)據(jù)信道(stdin),使之從指定的檔案讀進(jìn)。我們可用>來改變送出的數(shù)據(jù)信道(stdout,stderr),使之輸出到指定的檔案。比方說: $ cat < my.file
就是從my.file讀進(jìn)數(shù)據(jù) $ mail -s test root < /etc/passwd
則是從/etc/passwd 讀進(jìn)… 這樣一來,stdin將不再是從keyboard讀進(jìn),而是從檔案讀進(jìn)了…嚴(yán)格來說,< 符號(hào)之前需要指定一個(gè)FD的(之間不能有空白),但因?yàn)?code style="margin: 0px 0.15em; padding: 0px 0.3em; border-radius: 3px; border: 1px solid rgb(234, 234, 234); border-image: none; font-family: Consolas, Inconsolata, Courier, monospace; font-size: 0.85em; display: inline; white-space: pre-wrap; background-color: rgb(248, 248, 248);">0是< 的預(yù)設(shè)值,因此< 與0< 是一樣的!okay,這個(gè)好理解吧? 那,要是用兩個(gè)<< 又是啥呢?這是所謂的HERE Document ,它可以讓我們輸入一段文本,直到讀到<< 后指定的字串。比方說: $ cat <<FINISH
first line here
second line there
third line nowhere
FINISH
這樣的話,cat會(huì)讀進(jìn)3行句子,而無需從keyboard讀進(jìn)數(shù)據(jù)且要等^d結(jié)束輸入。至> 又如何呢?且聽下回分解… 11.3okay,又到講古時(shí)間~~~當(dāng)你搞懂了0< 原來就是改變stdin 的數(shù)據(jù)輸入信道之后,相信要理解如下兩個(gè)redirection就不難了:1> 2> 。前者是改變stdout 的數(shù)據(jù)輸出信道,后者是改變stderr 的數(shù)據(jù)輸出信道。兩者都是將原本要送出到monitor的數(shù)據(jù)轉(zhuǎn)向輸出到指定檔案去。 由于1 是> 的預(yù)設(shè)值,因此,1> 與> 是相同的,都是改變stdout 。用上次的ls例子來說明一下好了: $ ls my.file no.such.file 1>file.out
ls: no.such.file: No such file or directory
這樣monitor就只剩下stderr而已。因?yàn)閟tdout給寫進(jìn)file.out 去了。 $ ls my.file no.such.file 2>file.err
my.file
這樣monitor就只剩下stdout,因?yàn)閟tderr寫進(jìn)了file.err 。 $ ls my.file no.such.file 1>file.out 2>file.err
這樣monitor就啥也沒有,因?yàn)閟tdout與stderr都給轉(zhuǎn)到檔案去了… 呵~~~看來要理解> 一點(diǎn)也不難啦﹗是不?沒騙你吧?^_^ 不過,有些地方還是要注意一下的。 首先,是同時(shí)寫入的問題。比方如下這個(gè)例子: $ ls my.file no.such.file 1>file.both 2>file.both
假如stdout(1)與stderr(2)都同時(shí)在寫入file.both的話,則是采取“覆蓋”方式:后來寫入的覆蓋前面的。讓我們假設(shè)一個(gè)stdout與stderr同時(shí)寫入file.out的情形好了: - 首先stdout寫入10個(gè)字元
- 然后stderr寫入6個(gè)字元
那么,這時(shí)候原本stdout輸出的10個(gè)字元就被stderr覆蓋掉了。那,如何解決呢?所謂山不轉(zhuǎn)路轉(zhuǎn)、路不轉(zhuǎn)人轉(zhuǎn)嘛,我們可以換一個(gè)思維:將std
|