首页 > 代码库 > 使用exec

使用exec

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

使用exec重定向stdin

1 #!/bin/bash2 # 使用exec重定向stdin. 345 exec 6<&0 # 将文件描述符#6与stdin链接起来. 6 # 保存stdin. 78 exec < data-file # stdin被文件"data-file"所代替. 910 read a1 # 读取文件"data-file"的第一行. 11 read a2 # 读取文件"data-file"的第二行. 1213 echo14 echo "Following lines read from file."15 echo "-------------------------------"16 echo $a117 echo $a21819 echo; echo; echo2021 exec 0<&6 6<&-22 #  现在将stdin从fd #6中恢复, 因为刚才我们把stdin重定向到#6了, 23 #+ 然后关闭fd #6 ( 6<&- ), 好让这个描述符继续被其他进程所使用. 24 #25 # <&6 6<&-  这么做也可以. 2627 echo -n "Enter data "28 read b1 # 现在"read"已经恢复正常了, 就是能够正常的从stdin中读取.29 echo "Input read from stdin."30 echo "----------------------"31 echo "b1 = $b1"3233 echo3435 exit 0

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

exec N > filename会影响整个脚本或当前shell. 对于这个指定PID的脚本或shell来说,从这句命令执行之后, 就会重定向到这个文件中, 然而 . . .N > filename只会影响新fork出来的进程, 而不会影响整个脚本或shell. 

使用exec来重定向stdout

1 #!/bin/bash2 # reassign-stdout.sh34 LOGFILE=logfile.txt56 exec 6>&1 # 将fd #6与stdout链接起来. 7 # 保存stdout. 89 exec > $LOGFILE # stdout就被文件"logfile.txt"所代替了. 1011 # ----------------------------------------------------------- #12 # 在这块中所有命令的输出都会发送到文件$LOGFILE中. 1314 echo -n "Logfile: "15 date16 echo "-------------------------------------"17 echo1819 echo "Output of \"ls -al\" command"20 echo21 ls -al22 echo; echo23 echo "Output of \"df\" command"24 echo25 df2627 # ----------------------------------------------------------- #2829 exec 1>&6 6>&- # 恢复stdout, 然后关闭文件描述符#6. 3031 echo32 echo "== stdout now restored to default == "33 echo34 ls -al35 echo3637 exit 0

使用exec在同一个脚本中重定向stdin和stdout

1 #!/bin/bash2 # upperconv.sh3 # 将一个指定的输入文件转换为大写. 45 E_FILE_ACCESS=706 E_WRONG_ARGS=7178 if [ ! -r "$1" ] # 判断指定的输入文件是否可读? 9 then10 echo "Can‘t read from input file!"11 echo "Usage: $0 input-file output-file"12 exit $E_FILE_ACCESS13 fi #  即使输入文件($1)没被指定14 #+ 也还是会以相同的错误退出(为什么?). 1516 if [ -z "$2" ]17 then18 echo "Need to specify output file."19 echo "Usage: $0 input-file output-file"20 exit $E_WRONG_ARGS21 fi222324 exec 4<&025 exec < $1 # 将会从输入文件中读取. 2627 exec 7>&128 exec > $2 # 将写到输出文件中. 29 # 假设输出文件是可写的(添加检查?). 3031 # -----------------------------------------------32 cat - | tr a-z A-Z # 转换为大写. 33 # ^^^^^ # 从stdin中读取. 34 # ^^^^^^^^^^ # 写到stdout上. 35 # 然而, stdin和stdout都被重定向了. 36 # -----------------------------------------------3738 exec 1>&7 7>&- # 恢复stout.39 exec 0<&4 4<&- # 恢复stdin.4041 # 恢复之后, 下边这行代码将会如预期的一样打印到stdout上. 42 echo "File \"$1\" written to \"$2\" as uppercase conversion."4344 exit 0

I/O重定向是一种避免可怕的子shell中不可访问变量问题的方法.

避免子shell

1 #!/bin/bash2 # avoid-subshell.sh3 # 由Matthew Walker所提出的建议. 45 Lines=067 echo89 cat myfile.txt | while read line; # (译者注: 管道会产生子shell)10 do {11 echo $line12 (( Lines++ )); #  增加这个变量的值13 #+ 但是外部循环却不能访问. 14 #  子shell问题. 15 }16 done1718 echo "Number of lines read = $Lines" # 019 # 错误!2021 echo "------------------------"222324 exec 3<> myfile.txt25 while read line <&326 do {27 echo "$line"28 (( Lines++ )); #  增加这个变量的值29 #+ 现在外部循环就可以访问了. 30 #  没有子shell, 现在就没问题了. 31 }32 done33 exec 3>&-3435 echo "Number of lines read = $Lines" # 83637 echo3839 exit 0

 

使用exec