shell十三问-11) > 与 < 差在哪

�@次的�}目之前我在 CU 的 shell 版已�f明�^了:
(原�N�B�Y在���改版後已�失效)
�@次我就不重��了,�①N子的�热�"抄"下�砭褪橇�...

--------------
11.1
�到 I/O redirection ,不妨先�我���J�R一下 File Descriptor (FD) 。

程式的�\算,在大部份情�r下都是�M行���(data)的�理,
�@些����哪淖x�M?又,送出到哪�e呢?
�@就是 file descriptor (FD) 的功用了。

在 shell 程式中,最常使用的 FD 大概有三��,分�e�椋�
0: Standard Input (STDIN)
1: Standard Output (STDOUT)
2: Standard Error Output (STDERR)

在��是�r下,�@些 FD 分�e跟如下�O��(device)�P�:
stdin(0): keyboard
stdout(1): monitor
stderr(2): monitor

我��可以用如下下命令�y�一下:
 

  1. $ mail -s test root
     
  2. this is a test mail.
     
  3. please skip.
     
  4. ^d (同�r按 crtl 跟 d �I)
复制代码


很明�@,mail 程式所�x�M的���,就是�� stdin 也就是 keyboard �x�M的。
不�^,不�得每��程式的 stdin 都跟 mail 一��� keyboard �x�M,
因�槌淌阶髡呖梢��n案��底x�M stdin ,如:
 

  1. $ cat /etc/passwd
复制代码


但,要是 cat 之後�]有�n案���t又如何呢?
哦,�您自己玩玩看��.... ^_^
 

  1. $ cat
复制代码



(�留意����出到哪�e去了,最後�e忘了按 ^d �x�_...)

至於 stdout �c stderr ,嗯... 等我有空再�m吧... ^_^
�是,有哪位前�要�硗娼育�呢?

--------------
11.2
沿文再�m,��接上一回... ^_^

相信,��^上一����後,你�� stdin �c stdout ���不�y理解吧?
然後,�我���^�m看 stderr 好了。
事��上,stderr �]甚�N�y理解的:�f穿了就是"�e�`信息"要往哪�送而已...
比方�f,若�x�M的�n案��凳遣淮嬖诘模�那我��在 monitor 上就看到了:
 

  1. $ ls no.such.file
     
  2. ls: no.such.file: No such file or directory
复制代码



若,一��命令同�r�a生 stdout �c stderr 呢?
那�不��危�都送到 monitor �砭秃昧耍�
 

  1. $ touch my.file
     
  2. $ ls my.file no.such.file
     
  3. ls: no.such.file: No such file or directory
     
  4. my.file
复制代码



okay,至此,�P於 FD 及其名�Q、�有相�P�的�O�洌�相信你已��]���}了吧?
那好,接下�碜�我��看看如何改��@些 FD 的�A�O���通道,
我��可用 < �砀淖��x�M的���通道(stdin),使之�闹付ǖ�n案�x�M。
我��可用 > �砀淖�送出的���通道(stdout, stderr),使之�出到指定的�n案。

比方�f:
 

  1. $ cat < my.file
复制代码


就是�� my.file �x�M���
 

  1. $ mail -s test root < /etc/passwd
复制代码


�t是�� /etc/passwd �x�M...
�@�右�恚�stdin �⒉辉偈�� keyboard �x�M,而是��n案�x�M了...
�栏�碚f,< 符�之前需要指定一�� FD 的(之�g不能有空白),
但因�� 0 是 < 的�A�O值,因此 < �c 0< 是一�拥末u

okay,�@��好理解吧?
那,要是用��� << 又是啥呢?
�@是所�^的 HERE Document ,它可以�我���入一段文本,直到�x到 << 後指定的字串。
比方�f:
 

  1. $ cat <<FINISH
     
  2. first line here
     
  3. second line there
     
  4. third line nowhere
     
  5. FINISH
复制代码


�@�拥脑�,cat ���x�M 3 行句子,而�o需�� keyboard �x�M���且要等 ^d �Y束�入。

至於 > 又如何呢?
且�下回分解....

--------------
11.3
okay,又到�v古�r�g~~~

��你搞懂了 0< 原�砭褪歉淖� stdin 的����入通道之後,相信要理解如下��� redirection 就不�y了:
* 1>
* 2>
前者是改� stdout 的����出通道,後者是改� stderr 的����出通道。
�烧叨际�⒃�本要送出到 monitor 的����D向�出到指定�n案去。
由於 1 是 > 的�A�O值,因此,1> �c > 是相同的,都是改� stdout 。

用上次的 ls 例子�碚f明一下好了:

 

  1. $ ls my.file no.such.file 1>file.out
     
  2. ls: no.such.file: No such file or directory
复制代码


�@�� monitor 就只剩下 stderr 而已。因�� stdout �o���M file.out 去了。

 

  1. $ ls my.file no.such.file 2>file.err
     
  2. my.file
复制代码


�@�� monitor 就只剩下 stdout ,因�� stderr ���M了 file.err 。

 

  1. $ ls my.file no.such.file 1>file.out 2>file.err
复制代码


�@�� monitor 就啥也�]有,因�� stdout �c stderr 都�o�D到�n案去了...

呵~~~ 看�硪�理解 > 一�c也不�y啦�u是不?�]�_你吧? ^_^
不�^,有些地方�是要注意一下的。

首先,是同�r��入的���}。比方如下�@��例子:

 

  1. $ ls my.file no.such.file 1>file.both 2>file.both
复制代码


假如 stdout(1) �c stderr(2) 都同�r在��入 file.both 的�,
�t是�袢�“覆�w”方式:後���入的覆�w前面的。
�我��假�O一�� stdout �c stderr 同�r��入 file.out 的情形好了:
* 首先 stdout ��入10��字元
* 然後 stderr ��入 6 ��字元
那�N,�@�r候原本 stdout �出的 10 ��字元就被 stderr 覆�w掉了。

那,如何解�Q呢?所�^山不�D路�D、路不�D人�D嘛,
我��可以�Q一��思�S:�� stderr �нM stdout 或�� stdout �нM sterr ,而不是大家在��同一份�n案,不就行了�u
bingo�u就是�@�永玻�
* 2>&1 就是�� stderr �氵M stdout 作�出
* 1>&2 或 >&2 就是�� stdout �氵M stderr 作�出
於是,前面的�e�`操作可以改�椋�
 

  1. $ ls my.file no.such.file 1>file.both 2>&1
     

  2.  
  3. $ ls my.file no.such.file 2>file.both >&2
复制代码



�@�樱�不就皆大�g喜了�幔� 呵~~~ ^_^

不�^,光解�Q了同�r��入的���}�不�颍�我���有其他技巧需要了解的。
故事��]�Y束,�e走�_�u�V告後,我��再回��...�u


--------------
11.4
okay,�@次不�v I/O Redirction ,�v佛吧...
(有�]搞�e?�u�W中人是否�^����牧耍�...) 嘻~~~ ^_^

�W佛的最高境界,就是"四大皆空"。至於是空哪四大�K?我也不知,因�槲疫��]到那境界...
但�@��"空"字,�s非常值得我��返�}把玩的:
--- 色即是空、空即是色�u
好了,施主要是能�蝾I��"空"的�U意,那�x修成正果不�h矣~~~

在 Linux �n案系�y�e,有���O��n位於 /dev/null 。
�S多人都���^我那是甚�N玩意�海课腋�你�f好了:那就是"空"啦�u
�]�e�u空空如也的空就是 null 了.... ���施主是否忽然有所�D�`了呢?然�t恭喜了~~~ ^_^

�@�� null 在 I/O Redirection 中可有用得很呢:
* 若�� FD1 跟 FD2 �D到 /dev/null 去,就可�� stdout �c stderr 弄不�掉。
* 若�� FD0 接到 /dev/null �恚�那就是�x�M nothing 。
比方�f,��我��在�绦幸��程式�r,��面��同�r送出 stdout 跟 stderr ,
假如你不想看到 stderr (也不想存到�n案去),那可以:
 

  1. $ ls my.file no.such.file 2>/dev/null
     
  2. my.file
复制代码



若要相反:只想看到 stderr 呢?�不��惟u�� stdout 弄到 null 就行:
 

  1. $ ls my.file no.such.file >/dev/null
     
  2. ls: no.such.file: No such file or directory
复制代码



那接下�恚�假如�渭�只跑程式,不想看到任何�出�Y果呢?
哦,�@�e留了一手上次�目�]�v的法子,�iT�予有�人�u... ^_^
除了用 >/dev/null 2>&1 之外,你�可以如此:
 

  1. $ ls my.file no.such.file &>/dev/null
复制代码


(提示:�� &> �Q成 >& 也行啦~~! )

okay?�v完佛,接下�恚�再�我��看看如下情�r:
 

  1. $ echo "1" > file.out
     
  2. $ cat file.out
     
  3. 1
     
  4. $ echo "2" > file.out
     
  5. $ cat file.out
     
  6. 2
复制代码


看�恚�我��在重�� stdout 或 stderr �M一份�n案�r,似乎永�h只�@得最後一次��入的�Y果。
那,之前的�热菽兀�
呵~~~ 要解�Q�@����提很��卫玻��� > �Q成 >> 就好:
 

  1. $ echo "3" >> file.out
     
  2. $ cat file.out
     
  3. 2
     
  4. 3
复制代码


如此一�恚�被重�У哪��n案之�热�K不��失去,而新的�热�t一直增加在最後面去。
easy ? 呵 ... ^_^

但,只要你再一次用回�我坏� > �碇�У脑�,那�N,�f的�热葸�是��被"洗"掉的�u
�@�r,你要如何避免呢?
----�浞荸u yes ,我�到了�u不�^.... �有更好的�幔�
既然�c施主�@�N有�份,老�{就送你一���\囊妙法吧:
 

  1. $ set -o noclobber
     
  2. $ echo "4" > file.out
     
  3. -bash: file: cannot overwrite existing file
复制代码



那,要如何取消�@��"限制"呢?
哦,�� set -o �Q成 set +o 就行:
 

  1. $ set +o noclobber
     
  2. $ echo "5" > file.out
     
  3. $ cat file.out
     
  4. 5
复制代码



再��:那... 有�k法不取消而又"�R�r"�w��目��n案�幔�
哦,佛曰:不可告也�u
啊~~~ �_玩笑的、�_玩笑的啦~~~ ^_^ 唉,早就料到人心是不足的了�u
 

  1. $ set -o noclobber
     
  2. $ echo "6" >| file.out
     
  3. $ cat file.out
     
  4. 6
复制代码


留意到�]有:在 > 後面再加��" | "就好(注意: > �c | 之�g不能有空白哦)....

呼.... (深呼吸吐�{一下吧)~~~ ^_^
再�磉�有一���y�}要你去�⑼傅哪兀�
 

  1. $ echo "some text here" > file
     
  2. $ cat < file
     
  3. some text here
     
  4. $ cat < file > file.bak
     
  5. $ cat < file.bak
     
  6. some text here
     
  7. $ cat < file > file
     
  8. $ cat < file
复制代码



嗯?�u注意到�]有?�u�u
---- 怎�N最後那�� cat 命令看到的 file 竟是空的?�u
why? why? why?

同�W��:下��n不要�t到��~~~!


--------------
11.5
������~~~ 上�n��~~~ ^_^

前面提到:$ cat < file > file 之後原本有�热莸�n案�Y果�s被洗掉了�u
要理解�@一�F像其��不�y,�@只是 priority 的���}而已:
* 在 IO Redirection 中,stdout �c stderr 的管道��先��浜茫�才���� stdin �x�M�Y料。
也就是�f,在上例中,> file ��先�� file 清空,然後才�x�M < file ,
但�@�r候�n案已�被清空了,因此就�成�x不�M任何�Y料了...

哦~~~ 原�砣绱�~~~~ ^_^
那... 如下�衫�又如何呢?
 

  1. $ cat <> file
     
  2. $ cat < file >> file
复制代码



嗯... 同�W��,�@���答案就�����}�樱�下��n之前�交作�I�u

好了,I/O Redirection 也快�v完了,sorry,因�槲乙仓恢�道�@�N多而已啦~~~ 嘻~~ ^_^
不�^,�有一��|�|是一定要�v的,各位�^�(�自行配��~!#@!$%) :
---- 就是 pipe line 也�u

�到 pipe line ,我相信不少人都不��陌生:
我��在很多 command line 上常看到的" | "符�就是 pipe line 了。
不�^,究竟 pipe line 是甚�N�|�|呢?
�e急�e急... 先查一下英�h字典,看看 pipe 是甚�N意思?
�]�e�u它就是"水管"的意思...
那�N,你能想像一下水管是怎�N一根接著一根的�幔�
又,每根水管之�g的 input 跟 output 又如何呢?
嗯??
�`光一�W:原�� pipe line 的 I/O 跟水管的 I/O 是一模一�拥模�
* 上一��命令的 stdout 接到下一��命令的 stdin 去了�u
的�_如此... 不管在 command line 上你使用了多少�� pipe line ,
前後��� command 的 I/O 都是彼此�B接的�u(恭喜:你�K於�_�[了�u ^_^ )

不�^... 然而... 但是... ... stderr 呢?
好���}�u不�^也容易理解:
* 若水管漏水怎�N�k?
也就是�f:在 pipe line 之�g,前一��命令的 stderr 是不��接�M下一命令的 stdin 的,
其�出,若不用 2> �У� file 去的�,它�是送到�O�器上面�愆u
�@�c�你在 pipe line �\用上�毡匾�注意的。

那,或�S你又����:
* 有�k法�� stderr 也�j�M下一��命令的 stdin 去�幔�
(�得�o��的家夥�u)
方法��然是有,而且你早已�W�^了�u ^_^
我提示一下就好:
* ���你如何�� stderr 合�氵M stdout 一同�出呢?
若你答不出�恚�下�n之後再���我吧... (如果你�皮真�蚝竦脑�...)

或�S,你仍意尤未�M�u或�S,你曾�碰到�^下面的���}:
* 在 cm1 | cm2 | cm3 ... �@段 pipe line 中,若要�� cm2 的�Y果存到某一�n案呢?

若你��成 cm1 | cm2 > file | cm3 的�,
那你肯定���l�F cm3 的 stdin 是空的�u(��然啦,你都�⑺�管接到�e的水池了�u)
�明的你或�S��如此解�Q:
 

  1. cm1 | cm2 > file ; cm3 < file
复制代码


是的,你的�_可以�@�幼觯�但最大的�奶�是:�@�右�恚�file I/O ����p倍�u
在 command �绦械恼����^程中,file I/O 是最常�的最大效能�⑹帧�
凡是有��的 shell 操作者,都���M量避免或降低 file I/O 的�l率。

那,上面���}�有更好方法�幔�
有的,那就是 tee 命令了。
* 所�^ tee 命令是在不影�原本 I/O 的情�r下,�� stdout �}�u一份到�n案去。
因此,上面的命令行可以如此打:
 

  1. cm1 | cm2 | tee file | cm3
复制代码


在�A�O上,tee ��改��目��n案,若你要改�樵黾�热莸脑�,那可用 -a ��颠_成。

基本上,pipe line 的��用在 shell 操作上是非常�V泛的,尤其是在 text filtering 方面,
凡�e cat, more, head, tail, wc, expand, tr, grep, sed, awk, ... 等等文字�理工具,
搭配起 pipe line �硎褂茫�你���@�X command line 原�硎腔畹萌绱司�彩的�u
常�人有"��e�に�千百度,�然回首,那人�s在�艋痍@珊��u"之感... ^_^

....

好了,�P於 I/O Redirection 的介�B就到此告一段落。
若日後有空的�,再�榇蠹医榻B其它在 shell 上好玩的�|西�ubye... ^_^
 

你可能感兴趣的:(shell,十三问)