首页 > 编程知识 正文

标准输入输出重定向,输入输出重定向的使用

时间:2023-05-04 11:58:11 阅读:119001 作者:1269

默认情况下,始终打开三个“文件”。 屏幕上显示stdin、stdout、and stderr和错误信息。 这三个文件和其他打开的文件可以重定向。 重定向的简要说明是捕获一个文件、命令、程序、脚本或脚本中的代码块(例如

每个打开的文件都被分配一个文件描述符。 stdin、stdout和stderr的文件描述符分别为0、1和2。 打开的附加文件保留了描述符3-9。 在某些情况下,将这些特殊的文件描述符指定为stdin、stdout或stderr的临时复制链接非常有用。

1 COMMAND_OUTPUT

将stdout重定向到文件。

3 #如果没有此文件,则创建它,否则复盖它。

4

5 ls -lR dir-tree.list

创建包含6 #目录树列表的文件。

7

8 : filename

将9 #文件“文件名称”截断为0的长度。

如果10 #文件不存在,则创建长度为0的文件。 和“touch”有同样的效果。

11 # :是占位符,不产生任何输出。

12

13文件名称

将14 #文件“文件名”截断为0的长度。

如果15 #文件不存在,则创建长度为0的文件。 效果和“touch”一样。

效果与16 #上的“:”相同,但某些外壳可能无法正常工作。

17

18 COMMAND_OUTPUT

将19#stdout重定向到文件。

20 #”文件不存在,则创建它,如果存在,则添加到文件后面。

21

22

23 #单行重定向命令(仅影响它们所在的行) :

24--------------------------------------------?

25

26 1文件名称

将stdout重定向至27 #文件“文件名称”。

28 1文件名称

将stdout重定向到29 #文件“文件名”并添加到文件。

30 2文件名称

将31#stderr重定向至文件“文件名”。

3222文件名称

将33#stderr重定向到文件“filename”并将其添加。

34文件名称

将35#stdout和stderr重定向至文件“filename”。

36

37 #====================================

38#stdout一次重定向一行。

39 LOGFILE=script.log

40

41 echo ' thisstatementissenttothelogfile,'$LOGFILE'.' 1$LOGFILE

42 echo ' thisstatementisappendedto' $ log file'.'1$ log file

43 echo ' thisstatementisalsoappendedto' $ log file'.'1$ log file

44 echo ' thisstatementisechoedtostdout,and will not appear in '$LOGFILE'.'

45 #每行结束后,这些重定向命令将自动变为“reset”。

46

47

48

49#stderr一次重定向一行。

50 ERRORFILE=script.errors

51

52 bad_command1 2$ERRORFILE #错误消息已发送到$ERRORFILE。

53 bad_command2 2$ERRORFILE #错误消息将添加到$ERRORFILE中。

54 bad_command3 #错误消息从echo到stderr,

55 #然后不出现在$ERRORFILE中。

>

56 # 每行过后, 这些重定向命令也会自动"reset".

57 #==============================================================================

58

59

60

61 2>&1

62 # 重定向stderr到stdout.

63 # 得到的错误消息与stdout一样, 发送到一个地方.

64

65 i>&j

66 # 重定向文件描述符i 到 j.

67 # 指向i文件的所有输出都发送到j中去.

68

69 >&j

70 # 默认的, 重定向文件描述符1(stdout)到 j.

71 # 所有传递到stdout的输出都送到j中去.

72

73 0< FILENAME

74 < FILENAME

75 # 从文件中接受输入.

76 # 与">"是成对命令, 并且通常都是结合使用.

77 #

78 # grep search-word filename

82 # 为了读写"filename", 把文件"filename"打开, 并且分配文件描述符"j"给它.

83 # 如果文件"filename"不存在, 那么就创建它.

84 # 如果文件描述符"j"没指定, 那默认是fd 0, stdin.

85 #

86 # 这种应用通常是为了写到一个文件中指定的地方.

87 echo 1234567890 > File # 写字符串到"File".

88 exec 3<> File # 打开"File"并且给它分配fd 3.

89 read -n 4 &3 # 写一个小数点.

91 exec 3>&- # 关闭fd 3.

92 cat File # ==> 1234.67890

93 # 随机存储.

94

95

96

97 |

98 # 管道.

99 # 通用目的的处理和命令链工具.

100 # 与">"很相似, 但是实际上更通用.

101 # 对于想将命令, 脚本, 文件和程序串连起来的时候很有用.

102 cat *.txt | sort | uniq > result-file

103 # 对所有的.txt文件的输出进行排序, 并且删除重复行,

104 # 最后将结果保存到"result-file"中.

可以将输入输出重定向和(或)管道的多个实例结合到一起写在一行上.1 command < input-file > output-file

2

3 command1 | command2 | command3 > output-file参见 和 .

可以将多个输出流重定向到一个文件上.1 ls -yz >> command.log 2>&1

2 # 将错误选项"yz"的结果放到文件"command.log"中.

3 # 因为stderr被重定向到这个文件中,

4 #+ 所有的错误消息也就都指向那里了.

5

6 # 注意, 下边这个例子就不会给出相同的结果.

7 ls -yz 2>&1 >> command.log

8 # 输出一个错误消息, 但是并不写到文件中.

9

10 # 如果将stdout和stderr都重定向,

11 #+ 命令的顺序会有些不同.

关闭文件描述符

n

关闭输入文件描述符n.0, 关闭stdin.n>&-关闭输出文件描述符n.1>&-, >&-关闭stdout.

子进程继承了打开的文件描述符. 这就是为什么管道可以工作. 如果想阻止fd被继承, 那么可以关掉它.1 # 只重定向stderr到一个管道.

2

3 exec 3>&1 # 保存当前stdout的"值".

4 ls -l 2>&1 >&3 3>&- | grep bad 3>&- # 对'grep'关闭fd 3(但不关闭'ls').

5 # ^^^^ ^^^^

6 exec 3>&- # 现在对于剩余的脚本关闭它.

7

8 # Thanks, S.C.

如果想了解关于I/O重定向更多的细节参见 .

exec 命令会将stdin重定向到文件中. 从这句开始, 后边的输入就都来自于这个文件了, 而不是标准输入了(通常都是键盘输入). 这样就提供了一种按行读取文件的方法, 并且可以使用 和/或 来对每一行进行分析.

Example 16-1. 使用exec重定向标准输入

1 #!/hpdty/bash

2 # 使用'exec'重定向标准输入.

3

4

5 exec 6

同样的, exec >filename 命令将会把stdout重定向到一个指定的文件中. 这样所有的命令输出就都会发向那个指定的文件, 而不是stdout.

Example 16-2. 使用exec来重定向stdout

1 #!/hpdty/bash

2 # reassign-stdout.sh

3

4 LOGFILE=logfile.txt

5

6 exec 6>&1 # 将fd #6与stdout相连接.

7 # 保存stdout.

8

9 exec > $LOGFILE # stdout就被文件"logfile.txt"所代替了.

10

11 # ----------------------------------------------------------- #

12 # 在这块中所有命令的输出就都发向文件 $LOGFILE.

13

14 echo -n "Logfile: "

15 date

16 echo "-------------------------------------"

17 echo

18

19 echo "Output of "ls -al" command"

20 echo

21 ls -al

22 echo; echo

23 echo "Output of "df" command"

24 echo

25 df

26

27 # ----------------------------------------------------------- #

28

29 exec 1>&6 6>&- # 恢复stdout, 然后关闭文件描述符#6.

30

31 echo

32 echo "== stdout now restored to default == "

33 echo

34 ls -al

35 echo

36

37 exit 0

Example 16-3. 使用exec在同一脚本中重定向stdin和stdout

1 #!/hpdty/bash

2 # upperconv.sh

3 # 将一个指定的输入文件转换为大写.

4

5 E_FILE_ACCESS=70

6 E_WRONG_ARGS=71

7

8 if [ ! -r "$1" ] # 判断指定的输入文件是否可读?

9 then

10 echo "Can't read from input file!"

11 echo "Usage: $0 input-file output-file"

12 exit $E_FILE_ACCESS

13 fi # 即使输入文件($1)没被指定

14 #+ 也还是会以相同的错误退出(为什么?).

15

16 if [ -z "$2" ]

17 then

18 echo "Need to specify output file."

19 echo "Usage: $0 input-file output-file"

20 exit $E_WRONG_ARGS

21 fi

22

23

24 exec 4&1

28 exec > $2 # 将写到输出文件中.

29 # 假设输出文件是可写的(添加检查?).

30

31 # -----------------------------------------------

32 cat - | tr a-z A-Z # 转换为大写.

33 # ^^^^^ # 从stdin中读取.Reads from stdin.

34 # ^^^^^^^^^^ # 写到stdout上.

35 # 然而, stdin和stdout都被重定向了.

36 # -----------------------------------------------

37

38 exec 1>&7 7>&- # 恢复 stout.

39 exec 0

I/O重定向是一种避免可怕的问题的方法.

Example 16-4. 避免子shell

1 #!/hpdty/bash

2 # avoid-subshell.sh

3 # psdxyz Walker提出的建议.

4

5 Lines=0

6

7 echo

8

9 cat myfile.txt | while read line; # (译者注: 管道会产生子shell)

10 do {

11 echo $line

12 (( Lines++ )); # 增加这个变量的值

13 #+ 但是外部循环却不能存取.

14 # 子shell问题.

15 }

16 done

17

18 echo "Number of lines read = $Lines" # 0

19 # 错误!

20

21 echo "------------------------"

22

23

24 exec 3<> myfile.txt

25 while read line &-

34

35 echo "Number of lines read = $Lines" # 8

36

37 echo

38

39 exit 0

40

41 # 下边这些行是脚本的结果, 脚本是不会走到这里的.

42

43 $ cat myfile.txt

44

45 Line 1.

46 Line 2.

47 Line 3.

48 Line 4.

49 Line 5.

50 Line 6.

51 Line 7.

52 Line 8.

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。