linux shell I/O重定向小結

      材料總結,大部分內容及示例摘自《Advanced Bash-Scripting Guide》中chapt:An in-depth exploration of the art of shell scripting;需要詳細請自行參看。

       對於重定向簡單的解釋就是捕捉一個文件, 命令, 程序, 腳本, 或者甚至是腳本中的代碼塊的輸出, 然後將這些輸出作爲輸入發送到另一個文件, 命令, 程序, 或腳本中.

      默認情況下始終有3個"文件"處於打開狀態, stdin (鍵盤), stdout (屏幕), and stderr (錯誤消息輸出到屏幕上).

      每個打開的文件都會被分配一個文件描述符.stdin, stdout, 和stderr的文件描述符分別是0, 1, 和 2. 對於正在打開的額外文件, 保留了描述符3到9. 在某些時候將這些格外的文件描述符分配給stdin, stdout, 或者是stderr作爲臨時的副本鏈接是非常有用。並且在經過複雜的重定向和刷新之後需要把它們恢復成正常的樣子 

 

文件描述符:

表示範圍:  0-9

0-2:是系統定義好的。

         0:代表STDIN,標準輸入

         1:代表STDOUT,是標準輸出

          2:代表STDERR,是標準錯誤輸出

3-9:系統未定義,需要使用的可以自己定義使用

 

  1. COMMAND_OUTPUT > 
  2.       # 重定向stdout到一個文件. 
  3.       # 如果沒有這個文件就創建, 否則就覆蓋. 
  4.  
  5.    COMMAND_OUTPUT >> 
  6.      # 重定向stdout到一個文件. 
  7.       # 如果文件不存在, 那麼就創建它, 如果存在, 那麼就追加到文件後邊. 
  8.  
  9.  
  10.       # 單行重定向命令(只會影響它們所在的行): 
  11.     
  12.  #==========================================================
  13.    1>filename 
  14.       # 重定向stdout到文件"filename". 
  15.    1>>filename 
  16.       # 重定向並追加stdout到文件"filename". 
  17.    2>filename 
  18.       # 重定向stderr到文件"filename". 
  19.    2>>filename 
  20.       # 重定向並追加stderr到文件"filename". 
  21.    &>filename 
  22.       # 將stdout和stderr都重定向到文件"filename"
  23. #============================================================
  24.   2>&1
      # 重定向stderr到stdout.
      # 得到的錯誤消息與stdout一樣, 發送到一個地方.

      i>&j
    # 重定向文件描述符ij.
      # 指向i文件的所有輸出都發送到j中去.

      >&j
      # 默認的, 重定向文件描述符1(stdout)到 j.
      # 所有傳遞到stdout的輸出都送到j中去.

      0< FILENAME
      < FILENAME

      # 從文件中接受輸入.
      # 與">"是成對命令, 並且通常都是結合使用.
      #
      # grep search-word <filename
     
     
      [j]<>filename
      # 爲了讀寫"filename", 把文件"filename"打開, 並且分配文件描述符"j"給它.
      # 如果文件"filename"不存在, 那麼就創建它.
      # 如果文件描述符"j"沒指定, 那默認是fd 0, stdin.
      #
      # 這種應用通常是爲了寫到一個文件中指定的地方.
  25. 例:
      echo 1234567890 > File # 寫字符串到"File".
      exec 3<> File # 打開"File"並且給它分配fd 3.
      read -n 4 <&3 # 只讀4個字符.
      echo -n . >&3 # 寫一個小數點.
      exec 3>&- # 關閉fd 3.
      cat File # ==> 1234.67890
      # 隨機存儲.

 

可以將輸入輸出重定向的多個實例書寫到一行命令中

         #command < input-file > output-file

可以將多個輸出流重定向到一個文件上:

1 ls -yz >> command.log 2>&1
    #  將錯誤選項"yz"的結果放到文件"command.log"中.
    #  因爲stderr被重定向到這個文件中,
    #+ 所有的錯誤消息也就都指向那裏了.
    
    #  注意, 下邊這個例子就不會給出相同的結果.
    ls -yz 2>&1 >> command.log
    #  輸出一個錯誤消息, 但是並不寫到文件中.
    
    #  如果將stdout和stderr都重定向,
    #  命令的順序會有些不同.

 

 關閉文件描述符

n<&-

關閉輸入文件描述符n.

0<&-, <&-

關閉stdin.

n>&-

關閉輸出文件描述符n.

1>&-, >&-

關閉stdout.

使用exec:

   exec <filename

    命令會將stdin重定向到文件中. 從這句開始, 後邊的輸入就都來自於這個文件了, 而不是標準輸入了(通常都是鍵盤輸入). 這樣就提供了一種按行讀取文件的方法, 並且可以使用 sed 和 / 或 awk 來對每一行進行分析.

   exec >filename

    命令將會把stdout重定向到一個指定的文件中. 這樣所有的命令輸出就都會發向那個指定的文件, 而不是stdout.

 示例:exec重定向stdout

  1. #!/bin/bash 
  2. # reassign-stdout.sh 
  3.    
  4.   LOGFILE=logfile.txt 
  5.    
  6.   exec 6>&1           # 將fd 6 與stdout相連接. 
  7.                       # 保存stdout. 
  8.    
  9.  exec > $LOGFILE     # stdout就被文件"logfile.txt"所代替了    
  10.  #---------------------------------------------------------  
  11.  # 在這塊中所有命令的輸出就都發向文件 $LOGFILE. 
  12.   
  13.  echo -n "Logfile: " 
  14.  date 
  15.  echo "-------------------------------------" 
  16.  echo 
  17.   
  18.  echo "Output of \"ls -al\" command" 
  19.  echo 
  20.  ls -al 
  21.  echo; echo 
  22.  echo "Output of \"df\" command" 
  23.  echo 
  24.  df 
  25.   
  26.  # ----------------------------------------------------------- # 
  27.   
  28.  exec 1>&6 6>&-      # 恢復stdout, 然後關閉文件描述符6. 
  29.   
  30.  echo 
  31.  echo "== stdout now restored to default == " 
  32.  echo 
  33.  ls -al 
  34.  echo 
  35.   
  36.  exit 0 

示例:exec重定向stdout及stdin

  1. #!/bin/bash 
  2. # upperconv.sh 
  3. # 將一個指定的輸入文件轉換爲大寫. 
  4.    
  5.   E_FILE_ACCESS=70 
  6.   E_WRONG_ARGS=71 
  7.    
  8.  if [ ! -r "$1" ]     # 判斷指定的輸入文件是否可讀? 
  9.  then 
  10.    echo "Can't read from input file!" 
  11.    echo "Usage: $0 input-file output-file" 
  12.    exit $E_FILE_ACCESS 
  13.  fi                   #  即使輸入文件($1)沒被指定 
  14.                       #+ 也還是會以相同的錯誤退出(爲什麼?). 
  15.   
  16.  if [ -z "$2" ] 
  17.  then 
  18.    echo "Need to specify output file." 
  19.    echo "Usage: $0 input-file output-file" 
  20.    exit $E_WRONG_ARGS 
  21.  fi 
  22.   
  23.   
  24.  exec 4<&0 
  25.  exec < $1            # 將會從輸入文件中讀取. 
  26.   
  27.  exec 7>&1 
  28.  exec > $2            # 將寫到輸出文件中. 
  29.                       # 假設輸出文件是可寫的(添加檢查?). 
  30.   
  31.  # ----------------------------------------------- 
  32.      cat - | tr a-z A-Z   # 轉換爲大寫. 
  33.  #   ^^^^^                # 從stdin中讀取.Reads from stdin. 
  34.  #           ^^^^^^^^^^   # 寫到stdout上. 
  35.  # 然而, stdin和stdout都被重定向了. 
  36.  # ----------------------------------------------- 
  37.   
  38.  exec 1>&7 7>&-       # 恢復 stout. 
  39.  exec 0<&4 4<&-       # 恢復 stdin. 
  40.   
  41.  # 恢復之後, 下邊這行代碼將會如期望的一樣打印到stdout上. 
  42.  echo "File \"$1\" written to \"$2\" as uppercase conversion." 
  43.   
  44.  exit 0 

注:使用文件描述符5可能會引起問題. 當Bash使用exec創建一個子進程的時候, 子進程會繼承fd5. 最好還是不要用fd5

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章