有关重定向
有关重定向
Table of Contents
1 文件描述符处理
简单示例:
make 1> results 2> ERRS # 上面的命令是将make的标准输出(文件描述符1)传给results # 并将标准错误输出(文件描述符2)传给ERRS. make 1> results 2> /dev/null # 上面是将标准错误扔掉
注意: 1> result 里的 1 其实没有必要,供输出重定向的默认文件描述符是标准输出:也就是 文件描述符1 .
更进一步:
make > result 2>&1 # 重定向 > result 让文件描述符1(标准输出)作为文件results # 接下来的重定向 2>&1有两部分: # 一: 2> 重定向文件描述符2,也就是标准错误输出。 # 二: &1 是shell的语法:无论文件描述符1在哪里。 # 在本例中,文件描述符1是results文件,所以那里就是文件描述符2要附加的地方。
注意: 2>&1 必须连在一起,中间不能有任何空格。
2 exec 改变i/o
在使用exec时,如果只有I/O重定向而没有任何参数时,exec会改变shell的文件描述符:
exec 2> /tmp/$0.log #重定向shell本身的标准错误输出 exec 3< /some/file #打开新文件描述符3 ... read name rank serno <&3 #从该文件读取
3 Using exec
An exec <filename command redirects stdin to a file. From that point on, all stdin comes from that file, rather than its normal source (usually keyboard input). This provides a method of reading a file line by line and possibly parsing each line of input using sed and/or awk.
3.1 Example 16-1. Redirecting stdin using exec
#!/bin/bash # Redirecting stdin using 'exec'. exec 6<&0 # Link file descriptor #6 with stdin. # Saves stdin. exec < data-file # stdin replaced by file "data-file" read a1 # Reads first line of file "data-file". read a2 # Reads second line of file "data-file." echo echo "Following lines read from file." echo "-------------------------------" echo $a1 echo $a2 echo; echo; echo exec 0<&6 6<&- # Now restore stdin from fd #6, where it had been saved, #+ and close fd #6 ( 6<&- ) to free it for other processes to use. # # <&6 6<&- also works. echo -n "Enter data " read b1 # Now "read" functions as expected, reading from normal stdin. echo "Input read from stdin." echo "----------------------" echo "b1 = $b1" echo exit 0
Similarly, an exec >filename command redirects stdout to a designated file.
This sends all command output that would normally go to stdout to that file.
3.2 Example 16-2. Redirecting stdout using exec
#!/bin/bash # reassign-stdout.sh LOGFILE=logfile.txt exec 6>&1 # Link file descriptor #6 with stdout. # Saves stdout. exec > $LOGFILE # stdout replaced with file "logfile.txt". # ----------------------------------------------------------- # # All output from commands in this block sent to file $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>&- # Restore stdout and close file descriptor #6. echo echo "== stdout now restored to default == " echo ls -al echo exit 0
3.3 Example 16-3. Redirecting both stdin and stdout in the same script with exec
#!/bin/bash # upperconv.sh # Converts a specified input file to uppercase. E_FILE_ACCESS=70 E_WRONG_ARGS=71 if [ ! -r "$1" ] # Is specified input file readable? then echo "Can't read from input file!" echo "Usage: $0 input-file output-file" exit $E_FILE_ACCESS fi # Will exit with same error #+ even if input file ($1) not specified (why?). 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 # Will read from input file. exec 7>&1 exec > $2 # Will write to output file. # Assumes output file writable (add check?). # ----------------------------------------------- cat - | tr a-z A-Z # Uppercase conversion. # ^^^^^ # Reads from stdin. # ^^^^^^^^^^ # Writes to stdout. # However, both stdin and stdout were redirected. # ----------------------------------------------- exec 1>&7 7>&- # Restore stout. exec 0<&4 4<&- # Restore stdin. # After restoration, the following line prints to stdout as expected. echo "File \"$1\" written to \"$2\" as uppercase conversion." exit 0
I/O redirection is a clever way of avoiding the dreaded inaccessible variables within a subshell problem.
3.4 Example 16-4. Avoiding a subshell
#!/bin/bash # avoid-subshell.sh # Suggested by Matthew Walker. Lines=0 echo cat myfile.txt | while read line; do { echo $line (( Lines++ )); # Incremented values of this variable #+ inaccessible outside loop. # Subshell problem. } done echo "Number of lines read = $Lines" # 0 # Wrong! echo "------------------------" exec 3<> myfile.txt while read line <&3 do { echo "$line" (( Lines++ )); # Incremented values of this variable #+ accessible outside loop. # No subshell, no problem. } done exec 3>&- echo "Number of lines read = $Lines" # 8 echo exit 0 # Lines below not seen by script. $ cat myfile.txt Line 1. Line 2. Line 3. Line 4. Line 5. Line 6. Line 7. Line 8.
from http://www.linuxtopia.org/online_books/advanced_bash_scripting_guide/x13082.html
posted on 2013-04-12 11:19 liweilijie 阅读(212) 评论(0) 编辑 收藏 举报