材料總結,大部份內容及示例摘自《Advanced Bash-Scripting Guide》中chapt:An in-depth exploration of the art of shell scripting;須要詳細請自行參看。shell
對於重定向簡單的解釋就是捕捉一個文件, 命令, 程序, 腳本, 或者甚至是腳本中的代碼塊的輸出, 而後將這些輸出做爲輸入發送到另外一個文件, 命令, 程序, 或腳本中.bash
默認狀況下始終有3個"文件"處於打開狀態, stdin (鍵盤), stdout (屏幕), and stderr (錯誤消息輸出到屏幕上).ide
每一個打開的文件都會被分配一個文件描述符.stdin, stdout, 和stderr的文件描述符分別是0, 1, 和 2. 對於正在打開的額外文件, 保留了描述符3到9. 在某些時候將這些格外的文件描述符分配給stdin, stdout, 或者是stderr做爲臨時的副本連接是很是有用。而且在通過複雜的重定向和刷新以後須要把它們恢復成正常的樣子 ui
文件描述符:spa
表示範圍: 0-9rest
0-2:是系統定義好的。繼承
0:表明STDIN,標準輸入進程
1:表明STDOUT,是標準輸出ip
2:表明STDERR,是標準錯誤輸出ci
3-9:系統未定義,須要使用的能夠本身定義使用
- COMMAND_OUTPUT >
- # 重定向stdout到一個文件.
- # 若是沒有這個文件就建立, 不然就覆蓋.
- COMMAND_OUTPUT >>
- # 重定向stdout到一個文件.
- # 若是文件不存在, 那麼就建立它, 若是存在, 那麼就追加到文件後邊.
- # 單行重定向命令(只會影響它們所在的行):
- #==========================================================
- 1>filename
- # 重定向stdout到文件"filename".
- 1>>filename
- # 重定向並追加stdout到文件"filename".
- 2>filename
- # 重定向stderr到文件"filename".
- 2>>filename
- # 重定向並追加stderr到文件"filename".
- &>filename
- # 將stdout和stderr都重定向到文件"filename"
- #============================================================
- 2>&1
# 重定向stderr到stdout.
# 獲得的錯誤消息與stdout同樣, 發送到一個地方.
i>&j
# 重定向文件描述符i 到 j.
# 指向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.
#
# 這種應用一般是爲了寫到一個文件中指定的地方.- 例:
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.
關閉stdin.
關閉輸出文件描述符n.
關閉stdout.
使用exec:
exec <filename
命令會將stdin重定向到文件中. 從這句開始, 後邊的輸入就都來自於這個文件了, 而不是標準輸入了(一般都是鍵盤輸入). 這樣就提供了一種按行讀取文件的方法, 而且可使用 sed 和 / 或 awk 來對每一行進行分析.
exec >filename
命令將會把stdout重定向到一個指定的文件中. 這樣全部的命令輸出就都會發向那個指定的文件, 而不是stdout.
示例:exec重定向stdout
- #!/bin/bash
- # reassign-stdout.sh
- LOGFILE=logfile.txt
- exec 6>&1 # 將fd 6 與stdout相鏈接.
- # 保存stdout.
- exec > $LOGFILE # stdout就被文件"logfile.txt"所代替了
- #---------------------------------------------------------
- # 在這塊中全部命令的輸出就都發向文件 $LOGFILE.
- echo -n "Logfile: "
- date
- echo "-------------------------------------"
- echo
- echo "Output of \"ls -al\" command"
- echo
- ls -al
- echo; echo
- echo "Output of \"df\" command"
- echo
- df
- # ----------------------------------------------------------- #
- exec 1>&6 6>&- # 恢復stdout, 而後關閉文件描述符6.
- echo
- echo "== stdout now restored to default == "
- echo
- ls -al
- echo
- exit 0
示例:exec重定向stdout及stdin
- #!/bin/bash
- # upperconv.sh
- # 將一個指定的輸入文件轉換爲大寫.
- E_FILE_ACCESS=70
- E_WRONG_ARGS=71
- if [ ! -r "$1" ] # 判斷指定的輸入文件是否可讀?
- then
- echo "Can't read from input file!"
- echo "Usage: $0 input-file output-file"
- exit $E_FILE_ACCESS
- fi # 即便輸入文件($1)沒被指定
- #+ 也仍是會以相同的錯誤退出(爲何?).
- if [ -z "$2" ]
- then
- echo "Need to specify output file."
- echo "Usage: $0 input-file output-file"
- exit $E_WRONG_ARGS
- fi
- exec 4<&0
- exec < $1 # 將會從輸入文件中讀取.
- exec 7>&1
- exec > $2 # 將寫到輸出文件中.
- # 假設輸出文件是可寫的(添加檢查?).
- # -----------------------------------------------
- cat - | tr a-z A-Z # 轉換爲大寫.
- # ^^^^^ # 從stdin中讀取.Reads from stdin.
- # ^^^^^^^^^^ # 寫到stdout上.
- # 然而, stdin和stdout都被重定向了.
- # -----------------------------------------------
- exec 1>&7 7>&- # 恢復 stout.
- exec 0<&4 4<&- # 恢復 stdin.
- # 恢復以後, 下邊這行代碼將會如指望的同樣打印到stdout上.
- echo "File \"$1\" written to \"$2\" as uppercase conversion."
- exit 0
注:使用文件描述符5可能會引發問題. 當Bash使用exec建立一個子進程的時候, 子進程會繼承fd5. 最好仍是不要用fd5