有关重定向

有关重定向

有关重定向

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

Date: 2013-04-12 Fri

Author: liweilijie

Org version 7.9.2 with Emacs version 23

Validate XHTML 1.0

posted on 2013-04-12 11:19  liweilijie  阅读(212)  评论(0编辑  收藏  举报

导航