深入理解 bash redirection 重定向

stdout redirection

ganiks@bash-redirection  cat 123 
11111111
22222222
33333333ganiks@bash-redirection  cat 123 >> abc 
➜  ganiks@bash-redirection  echo "one line" >> abc

#当cat不带参数的时候,表示使用标准输入作为输入,这允许在标准输入中键入相关的内容ganiks@bash-redirection  cat >> abc
44444444
55555555
66666666^C    # ctrl+Cganiks@bash-redirection  cat abc 
11111111
22222222
33333333
one line
44444444
55555555
66666666

参考文档

stderr to stdout

ganiks@bash-redirection  cat > find.sh                                
find . -name "*" -print -exec grep "555" {} \;
^Cganiks@bash-redirection  sudo chmod +x find.sh
➜  ganiks@bash-redirection  ./find.sh 
.
grep: .: 是一个目录
./abc
55555555
./nginx-V
./find.sh
find . -name "*" -print -exec grep "555" {} \;
./123


#第一种情况ganiks@bash-redirection  ./find.sh 2>&1 > find1.log
grep: .: 是一个目录
grep: 输入文件 ‘./find1.log’ 同时也作输出
#第一种情况ganiks@bash-redirection  ./find.sh > find2.log 2>&1

#结果1ganiks@bash-redirection  cat find1.log 
.
./abc
55555555
./nginx-V
./find.sh
find . -name "*" -print -exec grep "555" {} \;
./123
./find1.log

#结果2 ganiks@bash-redirection  cat find2.log 
.
grep: .: 是一个目录
./abc
55555555
./nginx-V
./find.sh
find . -name "*" -print -exec grep "555" {} \;
./123
./find1.log
55555555
find . -name "*" -print -exec grep "555" {} \;
./find2.log
grep: 输入文件 ‘./find2.log’ 同时也作输出

0 是 stdin
1 是 stdout
2 是 stderr

➜ ganiks@bash-redirection ./find.sh 2>&1 > find1.log
➜ ganiks@bash-redirection ./find.sh > find2.log 2>&1

这里分析的关键是:一步一步分析,分析一步,输出一步

  • 第一种情况:
    • 2>&1: 将stderr定向到stdout, 原本stdout就是要到屏幕的,所以stderr会输出到屏幕
    • >find1.log: 将stdout 再重定向到文件
  • 第二种情况:
    • >find2.log: 将stdout重定向到文件
    • 2>&1: 将stderr重定向到stdout, 此时stdout已经到文件了,自然stderr也要到文件

重定向的过程其实很简单,但由于和直观感受不一致,往往导致初学者在这里犯很多错误。 参考文档

基本的IO重定向

基本IO重定向操作

  • > file: 将stdout重定向到file
  • < file: 将file作为stdin
  • cmd1 | cmd2 : pipe,将cmd1 的标准输出作为cmd2 的标准输入
  • >>file:将标准输出重定向到file,如果file存在,append到文件中,即附加到文件的后面,而不是覆盖文件
  • cat >> file: 当cat不带参数的时候,表示使用标准输入作为输入,这允许在标准输入中键入相关的内容
  • > | file: 强制将标准输出重定向到file,即使noclobber设置。当设置环境变量set –o noclobber,将禁止重定向到一个已经存在的文件中,避免文件被覆盖。
  • n >|file: 强制将文件描述符n重定向到file,即使noclobber打开
  • <>file: 将file作为标准输入和标准输出。通常用于设备文件(/dev下面的文件),底层系统程序员可用之测试设备驱动,其他的很少用
  • n <>file: 将file作为文件描述符n的输入和输出
  • << label: Here-document; : 将shell的标准输入作为命令的输入,直到行中之包含label。这中间的输入成为here-document。
ganiks@bash-redirection  cat >> msgfile <<.
heredoc> this is the text of
heredoc> our message
heredoc> end with .
heredoc> .   #这里<<.表明以.为结束。因此无需使用^D,而改用. 
➜  ganiks@bash-redirection  cat msgfile 
this is the text of
our message
end with .
  • n>file :将文件描述符n重定向到file
  • n :将file作为文件描述符的输入
  • n>>file :将文件描述符n的输出重定向到file,如果file存在,将输出append到文件后面
  • n>& :将标准输出复制到文件描述符n(Duplicate standard output to file descriptor n)
  • n<& :从文件描述符n复制标准输入(Duplicate standard input from file descriptor n)
  • n>&m :文件描述字n将一个copy至文件描述字m(File descriptor n is made to be a copy of the output file descriptor)
  • n<&m :文件描述字n作为文件描述字m中的一个拷贝(File descriptor n is made to be a copy of the input file descriptor)
  • &>file : 将标准输出和标准错误输出定向至文件file
  • <&- : 关闭标准输入
  • >&- : 关闭标准输出
  • n>&- : 关闭文件描述字作为输出(Close the output from file descriptor n)
  • n<&- :关闭文件描述字作输入(Close the input from file descriptor n)
  • n>&word: If n is not specified, the standard output (file descriptor 1) is used. If the digits in word do not specify a file descriptor open for output, a redirection error occurs. As a special case, if n is omitted, and word does not expand to one or more digits, the standard output and standard error are redirected as described previously.
  • n<&word : If word expands to one or more digits, the file descriptor denoted by n is made to be a copy of that file descriptor. If the digits in word do not specify a file descriptor open for input, a redirection error occurs. If word evaluates to -, file descriptor n is closed. If n is not specified, the standard input (file descriptor 0) is used.
  • n>&digit- : Moves the file descriptor digit to file descriptor n, or the standard output (file descriptor 1) if n is not specified.
  • n<&digit- : Moves the file descriptor digit to file descriptor n, or the standard input (file descriptor 0) if n is not specified. digit is closed after being duplicated to n.

文件描述符

文件描述符在bash中比较少用,从0开始用户表示进行的数据流,0表示标准输入,1表示标准输出,2表示标注错误输出,其他从3开始。
最为常用的场景是将错误消息输出到某个文件,可以加上2>file 到我们的命令中。
  
我们来看下面一个脚本的例子:

command > logfile 2>&1 &
  • >logfile 表示command的标准输出重定向至文件logfile中
  • 2>&1,匹配n>&m,表示文件描述字2(command的标准错误输出)将copy一份采用文件描述字1(即标准输出),由于标准输出已经重定向logfile,这份copy也见将重定向至文件lofgile。我们可以用“abcd > logfile 2>&1 &”来验证这个效果。

下面可达到类似的效果:

command 2>&1 | tee logfile &

错误输出同样适用标准输出,通过pipe方式,见他们作为输入执行tee logfile。tee命令将它的标准输入copy至他的标准标准输出以及参数所带的文件中。和上面的命令不一眼这里即会在stdout 和logfile中同时输出。

其他文件描述字的重定向,例如<&n,通常用于从多个文件中读入或者写出。

  • <&- ,表示强制关闭标准输入
  • >&- ,表示强制关闭标准输出
  • 1> ,等同于>
  • 0< ,等同于<

你可能感兴趣的:(深入理解 bash redirection 重定向)