回忆之城
生命在于折腾
posts - 575,comments - 9,trackbacks - 0

转载地址:http://blog.sina.com.cn/s/blog_87edb138010145ux.html

shell 在执行一个命令时,始终会打开三个文件,标准输入文件(stdin)、标准输出文件(stdout)、标准错误输出文件(stderr)。标准输入文件对应键盘、鼠标等输入设备;标准输出文件和标准错误文件对应显示器等输出设备。shell 启动的进程将从标准输入文件中得到输入数据,将正常输出数据输出到标准输出文件,而将错误信息送到标准错误文件。

在类 unix 系统中,系统为每一个打开的文件指定一个文件描述符(file descriptor)以便系统对文件进行跟踪。文件描述符和 c 语言的文件句柄相似,文件描述符是一个非负整数, 不同数字代表不同的含义。默认情况下,系统使用了三个,分别是 0、1、2。而 3 - 9 是保留的文件描述符。

0/1/2 文件描述符和文件的对应关系

 文件描述符  文件  文件  对应的设备
 0  标准输入文件  standard input
 keyboard、mouse
 1  标准输出文件  standard output
 monitor
 2  标准错误输出文件  standard error
 monitor

输入、输出重定向是一个过程,它捕捉一个文件、命令、程序、脚本、或者脚本中的代码块的输出(输入重定向),把捕捉到的输出作为输入发送给另外一个文件、命令、程序、脚本(输出重定向)。

标准输入重定向把文件、命令、程序、脚本的标准输入重定向到指定的文件中。也就是说,输入可以不来自键盘,而来自一个指定的文件。所以说,标准输入重定向主要用于改变一个命令的输入源,特别是改变那些需要大量输入的输入源。
标准输出重定向把文件、命令、程序、脚本的标准输出重定向到指定的文件中。这样就不必输出到显示器,而可以输出到一个指定的文件。

简单的标准输入输出重定向操作

 重定向操作  描述
 command < file
 标准输入重定向,command 从 file 中输入
 command > file
 标准输出重定向,command 的结果输出到 file 中
 command >> file
 标准输出重定向,command 的结果输出到 file 中

对于标准输出重定向来说,如果文件不存在,则生成文件,并将命令的输出写入到文件中。如果文件存在,> 重定向操作符将命令的输出覆盖文件的原有内容;而 >> 重定向操作符将命令的输出追加到文件的末尾。

示例 1

输入输出重定向" name=image_operate_87731343227984521 alt="shell 输入输出重定向" src="http://s6.sinaimg.cn/middle/87edb138h7a2a76a4c155&690">

输入输出重定向

 输入输出重定向  描述
 [n]<file
 重定向输入
 [n]>file  重定向输出
 [n]>>file  追加重定向输出
 &>file  重定向标准输出和标准错误输出
 >&file
 重定向标准输出和标准错误输出
 >file 2>&1
 重定向标准输出和标准错误输出
 &>>file
 追加重定向标准输出和标准错误输出
 >>file 2>&1
 追加重定向标准输出和标准错误输出
 command <<[-] here_limit_string  here 文档
 command <<< string  here 字符串
 [n]<>file  以读写方式打开文件描述符
 [n]<&-
 关闭输入文件描述符
 [n]>&-
 关闭输出文件描述符
 [n]<&digit
 复制输入文件描述符
 [n]>&digit
 复制输出文件描述符
 [n]<&digit-
 移动输入文件描述符
 [n]>&digit-
 移动输出文件描述符

重定向输入(redirecting input)
输入重定向引起文件(file 进行 shell 展开的结果)以读方式被打开,从文件描述符 n 输入的内容被定向为从文件读入。

语法格式如下:

    [n]<file

1 以读方式打开文件,并为文件分配文件描述符 n。
2 如果省略 n,则文件描述符为 0(即标准输入)。
3 注意 < 前后不能有空格;当 n 省略时,< 前后允许有空格。

重定向输出(redirecting output)
输出重定向引起文件(file 进行 shell 展开的结果)以写方式被打开,输出到文件描述符 n 的内容被定向为写入到文件。即重定向文件描述符 n 到文件

语法格式如下:

    [n]>file

1 以写方式打开文件,并为文件分配文件描述符 n。
2 如果省略 n,则文件描述符为 1(即标准输出)。
3 如果文件不存在,则创建文件;否则文件内容将被覆盖。
4 注意 > 前后不能有空格;当 n 省略时,> 前后允许有空格。

追加重定向输出(appending redirected output)

语法格式如下:

    [n]>>file

1 以追加写方式打开文件,并为文件分配文件描述符 n。
2 >> 和 > 一样,只是向文件写入内容的方式不一样。前者当文件存在时向文件追加内容;后者当文件存在时覆盖文件原有内容。
3 注意 >> 前后不能有空格;当 n 省略时,>> 前后允许有空格。

示例 2

输入输出重定向" name=image_operate_25911343313957111 alt="shell 输入输出重定向" src="http://s12.sinaimg.cn/middle/87edb138hc5bca5ba513b&690">

重定向标准输出和标准错误输出(redirecting standard output and standard error)
shell 允许标准输出(文件描述符为 1)和标准错误输出(文件描述符为 2)重定向到文件。

语法格式如下:

    &>file

或者

    >&file

等同于

    >file 2>&1

1 文件为 file 进行 shell 展开的结果。
2 两种形式在语法上是等同的,但提倡采用第一种方式。
3 如果文件不存在,则创建文件;否则文件内容将被覆盖。
4 &>file 和 >&file 在语法形式等同于 >file 2>&1。

追加重定向标准输出和标准错误输出(appending standard output and standard error)
shell 允许标准输出(文件描述符为 1)和标准错误输出(文件描述符为 2)以追加方式重定向到文件。

语法格式如下:

    &>>file

等同于

    >>file 2>&1

1 当文件不存在时,则创建文件;当文件存在时,则向文件追加内容。

示例 3

输入输出重定向" name=image_operate_51801343421577691 alt="shell 输入输出重定向" src="http://s3.sinaimg.cn/middle/87edb138hc5d5b5706292&690">

here documents
这种类型的重定向指示 shell 从当前来源读输入直到出现仅包含 here_limit_string 的一行。
详细描述请参考《shell here 文档》。

语法格式如下:

    command <<[-] here_limit_string
    ...
    ...
    here_limit_string

here strings
字符串(string 进行 shell 展开的结果)作为输入(代替标准输入)提供给命令。
详细描述请参考《shell here 文档》。

语法格式如下:

    command <<< string

以读写方式打开文件描述符(opening file descriptors for reading and writing)
输入输出重定向引起文件(file 进行 shell 展开的结果)在指定文件描述符处以读写方式被打开。

语法格式如下:

    [n]<>file

1 以读写方式打开文件,并为文件分配文件描述符 n
2 如果省略 n,则文件描述符为 0(即标准输入)。
3 如果文件不存在,则创建文件。
4 实际可以这样理解,为了读写文件,把文件打开,并分配文件描述符 n 给文件。

关闭文件描述符(close file descriptors)

语法格式如下:

    [n]<&-

1 表示关闭输入文件描述符 n。
2 如果省略 n,则文件描述符为 0(即标准输入)。

语法格式如下:

    [n]>&-

1 表示关闭输出文件描述符 n。
2 如果省略 n,则文件描述符为 1(即标准输出)。

示例 4
test.sh
 文件的内容如下
echo 123456789 > digit.txt

# open file descriptor
exec 3<>digit.txt

read -n 4 <&3
echo -n . >&3

# close file descriptor
exec 3>&-

number=$(cat < digit.txt)

echo number=$number

在命令提示符下输入 ./test.sh,执行结果如下:
number=1234.6789

复制文件描述符(duplicating file descriptors)
shell 允许将一个文件描述符复制到另外一个文件描述符,这样两个文件描述符将指向同一个文件。

语法格式如下:

    [n]<&digit

1 将文件描述符 digit 复制到文件描述符 n(如果省略 n,则文件描述符为 0(即标准输入))。从文件描述符 n 输入都将重定向为从文件描述符 digit 输入。
2 digit 是一个数字。

语法格式如下:

    [n]>&digit

1 将文件描述符 digit 复制到文件描述符 n(如果省略 n,则文件描述符为 1(即标准输出))。输出到文件描述符 n 的内容都将重定向输出到文件描述符 digit。
2 digit 是一个数字。

示例 5
test.sh
 文件的内容如下
echo "abc" > 1.txt
echo "def" > 2.txt

# open file descriptor
exec 3<1.txt
exec 4<2.txt

# duplicate file descriptor
exec 3<&4

echo "ghi" >> 2.txt
cat <&3

在命令提示符下输入 ./test.sh,执行结果如下:
def
ghi

示例 6
test.sh
 文件的内容如下
echo "abc" > 1.txt
echo "def" > 2.txt

# open file descriptor
exec 3<>1.txt
exec 4<>2.txt

# duplicate file descriptor
exec 3>&4

read -n 2 <&3
echo "ghi" >&3

# close file descriptor
exec 3>&-
exec 4>&-

content1=$(cat 1.txt)
content2=$(cat 2.txt)

echo content1=$content1
echo content2=$content2

在命令提示符下输入 ./test.sh,执行结果如下:
content1=abc
content2=deghi

移动文件描述符(moving file descriptors)
shell 允许将一个文件描述符移动到另外一个文件描述符。
shell 在将一个文件描述符复制到另外一个文件描述符之后,将原来的文件描述符关闭。

语法格式如下:

    [n]<&digit-

1 将文件描述符 digit 移动到文件描述符 n(如果省略 n,则文件描述符为 0(即标准输入))。
2 文件描述符将复制到文件描述符 n,之后文件描述符 digit 将关闭。文件描述符 digit 将不能再使用,否则会出错。
3 digit 是一个数字。

语法格式如下:

    [n]>&digit-

1 将文件描述符 digit 移动到文件描述符 n(如果省略 n,则文件描述符为 1(即标准输出))。
2 文件描述符将复制到文件描述符 n,之后文件描述符 digit 将关闭。文件描述符 digit 将不能再使用,否则会出错。
3 digit 是一个数字。

示例 7
test.sh
 文件的内容如下
echo "abc" > 1.txt
echo "def" > 2.txt

# open file descriptor
exec 3<>1.txt
exec 4<>2.txt

# duplicate file descriptor
exec 3>&4-

read -n 2 <&3
echo "ghi" >&3

read -n 2 <&4
echo "ghi" >&4

content1=$(cat 1.txt)
content2=$(cat 2.txt)

echo content1=$content1
echo content2=$content2

在命令提示符下输入 ./test.sh,执行结果如下:
./test.sh: line 14: 4: wrong file descriptor
./test.sh: line 15: 4: wrong file descriptor
content1=abc
content2=deghi

exec 命令和输入输出重定向
在默认情况下,shell 执行完重定向命令后,会自动 reset(输入、输出将恢复到标准输入、标准输出)。这样下面的命令将不会在进行重定向操作。
shell 提供了 exec 命令,当该命令执行重定向命令后,后边所有的操作(输入和输出),都不会被 reset。也就是说,后边所有的操作都是在重定向的基础上完成的。

exec 重定向标准输入
使用 exec < file,将会使 stdin 重定向到文件中。从这条命令开始,后边所有的输入都来自于文件,而不是标准输入了。

示例 8
test.sh 文件的内容如下
echo abc > 1.txt
echo def >> 1.txt

# save stdin
exec 6<&0

exec < 1.txt

read line1
read line2

# resume stdin and close fd #6
exec 0<&6 6<&-

echo line1=$line1
echo line2=$line2

在命令提示符下输入 ./test.sh,执行结果如下:
line1=abc
line2=def

exec 重定向标准输出
使用 exec > file,将会使 stdout 重定向到文件中。从这条命令开始,后边所有的输出到 stdout 的内容都将输出到文件,而不是标准输出了。

示例 9
test.sh 文件的内容如下
# save stdout
exec 6>&1

exec > 1.txt

# all stdout will output 1.txt
echo abc
echo def

# resume stdout and close fd #6
exec 1>&6 6>&-

content=$(cat 1.txt)
echo content=$content

在命令提示符下输入 ./test.sh,执行结果如下:
content=abc def

使用 exec 命令实现重定向 stdin 和 stdout,从一个文件读入并写入到另外一个文件。

示例 10
test.sh 文件的内容如下
input_file=1.txt
output_file=2.txt

echo 0001 > 1.txt
echo 0010 >> 1.txt
echo 0011 >> 1.txt

# save stdin and input redirect 1.txt
exec 6<&0
exec < 1.txt

# save stdout and output redirect 2.txt
exec 7>&1
exec > 2.txt

read num1
read num2
read num3

echo $((2#${num1} + 1))
echo $((2#${num2} + 2))
echo $((2#${num3} + 3))

# resume stdout and close fd #7
exec 1>&7 7>&-

# resume stdin and close fd #6
exec 0<&6 6<&-

# from here stdin and stdout are normal operate

在命令提示符下输入 ./test.sh,将在当前目录下生成 1.txt 和 2.txt。

在命令提示符下输入 cat 1.txt,执行结果如下:
0001
0010
0011

在命令提示符下输入 cat 2.txt,执行结果如下:
2
4
6

示例 11
test.sh 文件的内容如下
echo 0001 > 1.txt
echo 0010 >> 1.txt
echo 0011 >> 1.txt

exec 3<1.txt

while read <&3
do
    ((lines++))
done

exec 3<&-

echo 1.txt has $lines line

在命令提示符下输入 ./test.sh,执行结果如下:
1.txt has 3 line
posted on 2014-04-27 16:31 回忆之城 阅读(61) 评论(0)  编辑 收藏 引用 所属分类: unix/linux
只有注册用户登录后才能发表评论。