重定向标准输出
> 重定向当前命令的标准输出(STDOUT)到一个文件或者一个描述符。
下面的例子把ls命令的输出存到file.txt文件
ls >file.txt
> file.txt ls
目标文件如果不存在就会被创建,或者文件被截断。
如果不指定,默认重定向描述符是标准输出或1。下面的命令等同于上面的例子:
ls 1>file.txt
追加 vs 截断
截断 >
1.如果文件不存在则创建
2.截断(删除文件内容)
3.写入文件
$ echo "first line" > /tmp/lines
$ echo "second line" > /tmp/lines
$ cat /tmp/lines
second line
追加 >>
1.如果文件不存在则创建
2.追加文件(在文件底部写)
# Overwrite existing file
$ echo "first line" > /tmp/lines
# Append a second line
$ echo "second line" >> /tmp/lines
$ cat /tmp/lines
first line
second line
重定向标准输出和标准错误
文件描述符像0和1都是指针。我们更改的是文件描述符的指向。
>/dev/null意思是1指向/dev/null。
首先我们把1(STDOUT)指向/dev/null,然后2指向1(不管1指向什么)。
echo_to_stdout_and_stderr >/dev/null 2>&1
可以更短点:
echo_to_stdout_and_stderr &> /dev/null
使用命名管道
有时候你想把一个程序的标准输出作为其它多个程序的标准输入,这时候就不能用标准管道了,不过你可以写入一个临时文件,如:
touch tempFile.txt
ls -l > tempFile.txt &
grep ".log" < tempFile.txt
这个方法可以在大多数情况下有效,但谁都不知道tempFile.txt会被哪个程序删除或者修改里面的内容。这时候命名管道就可以用上场了。
mkfifo myPipe
ls -l > myPipe
grep ".log" < myPipe
myPipe在技术上是一个文件,所以我们来用ls -l看下当前创建管道的目录
mkdir pipeFolder
cd pipeFolder
mkfifo myPipe
ls -l
输出为:
prw-r–r– 1 root root 0 Jul 25 11:20 myPipe
注意权限的第一个字符,显示是pipe,不是文件。
现在我们做了有意思的。
打开一个终端,在一个空目录创建管道:
mkfifo myPipe
现在我们输入点东西到管道:
echo "Hello from the other side" > myPipe
你会注意到这个命令被挂起了,让我们打开一个新的终端,输入:
cat < myPipe
你会发现当”hello from the other side”输出后,终端1就完成了,终端2也一样。
现在我们反向运行程序,先执行cat < myPipe,然后再输入点东西到myPipe,它仍然按预期工作,因为一个程序会一起等待直到管道中被输入一些东西。 命名管道在终端间或程序间传递信息时会非常有用。
输出错误信息到标准错误
错误信息通常为了调度会包含在脚本里。简单的输出错误信息如下:
cmd || echo 'cmd failed'
可能会在简单的场景工作,但不是通常的做法。在这个例子中,错误信息会会污染脚本实际的输出。简单来说,错误信息应该输出到标准错误而不是标准输出,如:
cmd || echo 'cmd failed' >/dev/stderr
其它例子:
if cmd; then
echo 'success'
else
echo 'cmd failed' >/dev/stderr
fi
可以封装成一个函数:
err(){
echo "E: $*" >>/dev/stderr
}
err "My error message"