文件描述符是与文件输入、输出相关联的整数。他们用来跟踪已打开的文件。最常见的文件描述符是stdin、stdout和stderr。我们甚至可以将某个文件描述符的内容重定向到另一个文件描述符中。
1、玩转文件描述符及重定向
文件描述符是与某个打开的文件或数据流相关联的整数。文件描述符0,1以及2是系统预留的。
0---stdin(标准输入)
1---stdout(标准输出)
2---stderr(标准错误)
2、用下面的方法可以将输出文本重定向或保存到一个文件中:
echo "This is a sample text 1" > temp.txt
这种方法通过截断文件的方式,将输出文本存储到文件temp.txt中,也就是说在把echo命令的输出写入文件之前,temp.txt中的内容首先会被清空。
3、将文本追加到目标文件中,
echo "This is sample text 2" >> temp.txt
4、查看文件内容
cat temp.txt
5、来看看什么是标准错误以及如何对它重定向。当命令输出错误信息时,stderr信息就会被打印出来,如下
ls +
ls:cannot access +:No such file or directory
这里,+是一个非法参数,因此将返回错误信息。
成功或不成功的命令:当一个命令发生错误并退回时,它会返回一个非0的退出状态;而当命令成功完成后,它会返回数字0.退出状态可以从特殊变量$?中获得(在命令执行之后立刻运行echo $?,就可以打印出退出状态)。
下面的命令会将stderr文本打印到屏幕上,而不是文件中(因为没有stdout的输出,所以out.txt没有内容)
ls + > out.txt
ls:cannot access +:No such file or directory
下面的命令中,我们将stderr重定向到out.txt:
ls + 2>out.txt
我们还可以将stderr单独重定向到一个文件,将stdout重定向到另一个文件:
cmd 2>stderr.txt 1>stdout.txt
还可以将stderr转换成stdout,使得stderr和stdout都被重定向到同一个文件中:
cmd 2>&1 output.txt
等价于
cmd &> output.txt
6、如果不希望在输出中包含一些关于stderr不必要的信息,那么可以将stderr的输出重定向到/dev/null.
touch a1
cp a1 a2; a2 a3;
chmod 000 a1
cat a*
cat:a1:permission denied
其中 cat:a1:permission denied属于stderr;我们可以将stderr信息重定向到一个文件中,而stdout仍然保持不变。
cat a* 2> err.txt #stderr被重定向到err.txt
cat err.txt
cat:a1:permission denied
观察下面的代码
cmd 2>/dev/null
当如果对stderr或stdout进行重定向,被重定向的文本会传入文件。因为文本已经被重定向到文件中,也就没剩下什么东西可以通过管道(|)传给接下来的命令,而这些命令是通过stdin进行接收的。
7、但是有一个方法既可以将数据重定向到文件,还可以提供一份重定向数据的副本作为后续命令的stdin。可以使用tee来实现。eg:要在终端中打印stdout,同时将它重定向到一个文件中,
command | tee FILE1 FILE2
eg:cat a* | tee out.txt | cat -n
cat:a1:permission denied
1 a1
2 a2
在上面的代码中,tee命令接收到来自stdin的数据。它将stdout的一份副本写入文件out.txt,同时将另一份副本作为后续命令的stdin。命令cat -n将从stdin中接收到的每一行数据前加上行号并写入stdout。
注意,cat:a1:permission denied并没有在文件内容中出现,这是因为这些信息属于stderr,而tee只能从stdin中读取。
默认情况下,tee命令会将文件覆盖,但它提供了一个-a选项,用于追加内容,如
$cat a* | tee -a out.txt | cat -n.
设备文件/dev/stderr代表标准错误stderr;
/dev/stdout代表标准输出stdout;
/dev/stdin代表标准输入stdin;
工作原理:
就输出重定向而言,>和>>并不相同。尽管两者可以将文本重定向到文件,但是前者会先清空文件,然后重写入内容,而后者会将内容追加到现有文件的尾部。
重定向操作符默认使用标准输出。>等价于1>;>>等价于1>>
处理错误时,来自stderr的输出被丢弃到文件/dev/null中,/dev/null是一个特殊的设备文件,他接收到的任何数据都会被丢弃,null设备通常也被成为黑洞。
8、从stdin读取输入的命令能以多种方式接收数据。也可以用cat和管道来指定我们自己的文件描述符,如
cat file | cmd
cmd1 | cmd
a、将文件重定向到命令
借助重定向,可以像使用stdin那样从文件中读取数据:
cmd < file
b、将脚本内部的文本块进行重定向
源文本就位于shell脚本中。如向log文件中写入头部数据
#!/bin/bash
cat<<EOF>log.txt
LOG FILE HEADER
This is a test log file
Function: System statistics
EOF
在cat <<EOF>log.txt与下一个EOF行之间的所有文本都会被当作stdin数据。log.txt文件的内容打印如下:
cat log.txt
LOG FILE HEADER
This is a test log file
Function: System statistics
c、自定义文件描述符
文件描述符是一种用于访问文件的抽象指示器。存取文件离不开被称为“文件描述符”的特殊数字。
我们可以使用exec命令创建自己的文件描述符。文件打开模式一般有:
只读模式、截断写入模式、追加写入模式。
<操作符用于从文件中读取至stdin。>操作符用于截断模式的文件写入(数据在目标文件内容被截断之后写入)。>>操作符用于追加模式的文件写入。文件描述符可以用以上三种模式中的任意一种来创建。
创建一个文件描述符进行文件读取:
eg:exec 3<input.txt #使用文件描述符3打开读取文件
可以这样使用它:
echo this is a test line > input.txt
exec 3<input.txt
那么接下来就可以在命令中使用文件描述符3了。例如
cat <&3
结果:this is a test line
如果要再次读取,就不能继续使用文件描述符3了,而是需要用exec重新分配文件描述符3来进行二次读取。
创建一个文件描述符用于写入(截断模式)
exec 4>output.txt #打开文件进行写入
eg:
exec 4>output.txt
echo newline >&4
cat output.txt
结果:newline
创建一个文件描述符用于写入(追加模式)
exec 5>>input.txt
eg:
exec 5>>input.txt
echo appended line >&5
cat input.txt
结果:
newline
appended line