shell IO重定向

  1. I/O重定向

  默认情况下,有3个“文件”处于打开状态,stdin,stdout,stderr;重定向的解释:捕捉一个文件,命令,程序,脚本或者脚本中的代码块的输出,然后将这些输出作为输入发送到另一个文件,命令,程序或者脚本中。

  每个打开的文件都会被分配一个文件描述符,stdin,stdout,stderr的文件描述符分别是0,1,2.除了这3个文件,对于其他需要打开的文件,保留文件描述符3~9.在某些情况下,将这些额外的文件描述符分配给stdin,stdout或stderr作为临时的副本链接也是非常有用的。在经过复杂的重定向和刷新之后需要把他们恢复成正常状态。可以使用shell内建ulimit -n查看最大文件描述符,一般未1024.

ulimit描述如下:

              -a     All current limits are reported
              -b     The maximum socket buffer size
              -c     The maximum size of core files created
              -d     The maximum size of a process's data segment
              -e     The maximum scheduling priority ("nice")
              -f     The maximum size of files written by the shell and its children
              -i     The maximum number of pending signals
              -l     The maximum size that may be locked into memory
              -m     The maximum resident set size (many systems do not honor this limit)
              -n     The maximum number of open file descriptors (most systems do not allow this value to be set)
              -p     The pipe size in 512-byte blocks (this may not be set)
              -q     The maximum number of bytes in POSIX message queues
              -r     The maximum real-time scheduling priority
              -s     The maximum stack size
              -t     The maximum amount of cpu time in seconds
              -u     The maximum number of processes available to a single user
              -v     The maximum amount of virtual memory available to the shell and, on some systems, to its children
              -x     The maximum number of file locks
              -T     The maximum number of threads
    
View Code

ulimit -a结果如下:

core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 513989
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 4096
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited
View Code
 1 COMMAND_OUTPUT >
 2 #将stdout重定向到一个文件,如果这个文件不存在,就创建,否则就覆盖
 3 : > filename
 4 #将filename变成一个空文件(size=0); 
 5 # :是一个占位符,不产生任何输出
 6  > filename
 7 #同上,某些shell可能不支持
 8 
 9 COMMAND_OUTPUT >>
10 #将stdout重定向到一个文件,如果这个文件不存在,就创建,否则就追加
11 1> filename
12 #重定向stdout到filename; 
13 1>> filename
14 #重定向并追加stdout到filename; 
15 
16 M>N
17 #M是文件描述符,默认是1;N是一个文件名;文件描述符M被重定向到文件N
18 
19 M>&N
20 #M是文件描述符,默认是1;N是一个文件描述符;文件描述符M被重定向到文件N
21 
22 2>&1
23 #重定向stderr到stdout,将错误消息的输出,发送到与标准输出所指向的方向
24 
25 i>&j
26 #重定向描述符i到j,默认i是1
27 
28 0<FILENAME
29   <FILENAME
30 #从文件中接受输入
31 
32 [j]<>filename
33 #为了读写filename,把filename打开,并且将文件描述符j分配给它;如果filename不存在,就创建;如果描述符j没指定,默认fd 0,stdin
34  echo 1234567890 > File    # 写字符串到"File".
35  exec 3<> File             # 打开"File"并且将fd 3分配给它.
36  read -n 4 <&3             # 只读取4个字符.
37  echo -n . >&3             # 写一个小数点
38  exec 3>&-                 # 关闭fd 3.
39  cat File                  # ==> 1234.67890
View Code
 1 n<&-
 2 #关闭输入文件描述符n
 3 
 4 0<&-,<&-
 5 #关闭stdin
 6 
 7 n>&-
 8 #关闭输出文件描述符n
 9 
10 1>&-,>&-
11 #关闭stdout
View Code

    2. 使用exec进行I/O重定向

参考资料:http://www.linuxplus.org/kb/x13380.html

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

使用exec进行IO重定向可以避免子shell的产生

 1 #!/bin/bash
 2 #avoid_subshell.sh
 3 
 4 Lines=0
 5 echo
 6 cat myfile.txt | while read line; #管道会产生子shell
 7                     do {
 8                         echo $line
 9                         (( Lines++ )); #Lines的自加属于子shell范围,外部不能访问
10                         echo "in while Lines is $Lines"
11                     }
12                   done
13 
14 echo "Number of lines read = $Lines"  #结果为0,显示的结果是错误的
15 echo "------------------------"                  
16 
17 exec 3<> myfile.txt  #使用exec打开文件,使用文件描述符3
18 while read line <&3
19 do {
20     echo "$line"
21     (( Lines++ )); #不会产生子shell
22 }
23 done
24 exec 3>&-
25 echo "Number of lines read = $Lines"       #Lines输出的值是正确的
26 exit 0
View Code

上述代码中应该增加一行"exec 3<&-";原因:使用<>打开文件的读写操作之后,在关闭时,需要分别关闭文件的读和写,需要分开操作。

其中,myfile.txt的内容如下:

1 Line 1.
2 Line 2.
3 Line 3.
4 Line 4.
5 Line 5.
6 Line 6.
7 Line 7.
8 Line 8.
View Code

    3. 代码块重定向

参考资料:http://www.linuxplus.org/kb/redircb.html

下面是for循环的重定向example:

 1 #!/bin/bash
 2 
 3 if [ -z "$1" ]
 4 then
 5     Filename=names.data #
 6 else
 7     Filename=$1
 8 fi
 9 
10 #Filename=${1:-names.data} #这句可以代替上面的if语句(参数替换)
11 
12 
13 Savefile=$Filename.new #保存最终结果的文件
14 FinalName=Jonah #终止“read”时的名称
15 
16 line_count=`wc $Filename | awk '{ print $1 }'` #目标文件的行数
17 echo "line_count=$line_count"
18 
19 for name in `seq $line_count` #seq会打印出数字序列
20 do
21     read name 
22     echo "$name"
23     if [ "$name" = "$FinalName" ]
24     then
25         break
26     fi
27 done < "$Filename" > "$Savefile"    #重定向stdin到文件$Filename,
28 #             将输出重定向到$Savefile文件
29 
30 exit 0            
View Code
原文地址:https://www.cnblogs.com/zhiminyu/p/12520828.html