有关重定向
有关重定向
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 阅读(226) 评论(0) 收藏 举报
浙公网安备 33010602011771号