Bash使用示例(4) – 重定向输出

重定向标准输出



> 重定向当前命令的标准输出(STDOUT)到一个文件或者一个描述符。
下面的例子把ls命令的输出存到file.txt文件

  1. ls >file.txt
  2. > file.txt ls

目标文件如果不存在就会被创建,或者文件被截断。
如果不指定,默认重定向描述符是标准输出或1。下面的命令等同于上面的例子:

  1. ls 1>file.txt

追加 vs 截断



截断 >
1.如果文件不存在则创建
2.截断(删除文件内容)
3.写入文件

  1. $ echo "first line" > /tmp/lines
  2. $ echo "second line" > /tmp/lines
  3.  
  4. $ cat /tmp/lines
  5. second line

追加 >>
1.如果文件不存在则创建
2.追加文件(在文件底部写)

  1. # Overwrite existing file
  2. $ echo "first line" > /tmp/lines
  3.  
  4. # Append a second line
  5. $ echo "second line" >> /tmp/lines
  6.  
  7. $ cat /tmp/lines
  8. first line
  9. second line

重定向标准输出和标准错误



文件描述符像0和1都是指针。我们更改的是文件描述符的指向。
>/dev/null意思是1指向/dev/null。
首先我们把1(STDOUT)指向/dev/null,然后2指向1(不管1指向什么)。

  1. echo_to_stdout_and_stderr >/dev/null 2>&1

可以更短点:
echo_to_stdout_and_stderr &> /dev/null

使用命名管道



有时候你想把一个程序的标准输出作为其它多个程序的标准输入,这时候就不能用标准管道了,不过你可以写入一个临时文件,如:

  1. touch tempFile.txt
  2. ls -l > tempFile.txt &
  3. grep ".log" < tempFile.txt

这个方法可以在大多数情况下有效,但谁都不知道tempFile.txt会被哪个程序删除或者修改里面的内容。这时候命名管道就可以用上场了。

  1. mkfifo myPipe
  2. ls -l > myPipe
  3. grep ".log" < myPipe

myPipe在技术上是一个文件,所以我们来用ls -l看下当前创建管道的目录

  1. mkdir pipeFolder
  2. cd pipeFolder
  3. mkfifo myPipe
  4. ls -l

输出为:
prw-r–r– 1 root root 0 Jul 25 11:20 myPipe
注意权限的第一个字符,显示是pipe,不是文件。
现在我们做了有意思的。
打开一个终端,在一个空目录创建管道:

  1. mkfifo myPipe

现在我们输入点东西到管道:

  1. echo "Hello from the other side" > myPipe

你会注意到这个命令被挂起了,让我们打开一个新的终端,输入:

  1. cat < myPipe

你会发现当”hello from the other side”输出后,终端1就完成了,终端2也一样。
现在我们反向运行程序,先执行cat 输出错误信息到标准错误



错误信息通常为了调度会包含在脚本里。简单的输出错误信息如下:

  1. cmd || echo 'cmd failed'

可能会在简单的场景工作,但不是通常的做法。在这个例子中,错误信息会会污染脚本实际的输出。简单来说,错误信息应该输出到标准错误而不是标准输出,如:

  1. cmd || echo 'cmd failed' >/dev/stderr

其它例子:

  1. if cmd; then
  2.     echo 'success'
  3. else
  4.     echo 'cmd failed' >/dev/stderr
  5. fi

可以封装成一个函数:

  1. err(){
  2.     echo "E: $*" >>/dev/stderr
  3. }
  4. err "My error message"
标签:Bash 发布于:2019-11-21 02:16:57