玩转文件描述符及重定向

返回主页面

 

文件描述符是与文件输入、输出相关联的整数。它们用来跟踪已打开的文件。最常见的文件 描述符是stdinstdoutstderr。我们甚至可以将某个文件描述符的内容重定向到另一个文 件描述符中。下面给出一些对文件描述符进行操作和重定向的例子。

 

 

在编写脚本的时候会频繁使用标准输入(stdin)、标准输出(stdout)和标准错误 (stderr)。通过内容过滤将输出重定向到文件是我们平日里的基本任务之一。当命令输出文本 时,这些输出文本有可能是错误信息,也可能是正常的(非错误的)输出信息。单靠查看输出的

文本本身,我们没法区分哪些是正常,哪些是错误。不过可以通过文件描述符来解决这个问题,
将那些与特定描述符关联的文本提取出来。

文件描述符是与某个打开的文件或数据流相关联的整数。文件描述符01以及2是系统预留的。

0 —— stdin(标准输入)。 1 —— stdout(标准输出)。 2 —— stderr(标准错误)。

 

实例

 

(1) 将输出文本重定向或保存到一个文件中:

 

echo "This is a sample text 1" > temp.txt

这种方法通过截断文件的方式,将输出文本存储到文件temp.txt中,也就是说在把 echo命令的输出写入文件之前,temp.txt中的内容首先会被清空。

 

 

(2) 将文本追加到目标文件中

 

echo "This is sample text 2" >> temp.txt

 

>cat temp.txt
This is sample text 1
This is sample text 2

 

(3) 标准错误以及如何对它重定向。当命令输出错误信息时,stderr信息 就会被打印出来。考虑下面的例子:

 

$ ls +

ls: cannot access +: No such file or directory

这里,+是一个非法参数,因此将返回错误信息。

-------------------------------------------------------------------------------

下面的命令会将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,使得stderrstdout 都被重定向到同一个文件中:

$ cmd 2>&1 output.txt

或者这样:

$ cmd &> output.txt

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

(4)有时候,在输出中可能包含一些不必要的信息(比如调试信息)。如果你不想让终端 中充斥着有关stderr的繁枝末节,那么你可以将stderr的输出重定向到 /dev/null

保证一切都会被清除得干干净净。假设我们有3个文件,分别是a1a2a3。但是普 通用户对文件a1没有“读 执行”权限。

如果需要打印文件名以a起始的所有文件 的内容,可以使用cat命令。设置一些测试文件:

 

$ echo a1 > a1
$ cp a1 a2 ; cp a2 a3;
$ chmod 000 a1 #清除所有权限

尽管可以使用通配符(a*)显示所有的文件内容,但是系统会显示一个出错信息, 因为对文件a1没有可读权限。

 

$ cat a*
   cat: a1: Permission denied
   a1
   a1

其中,cat: a1: Permission denied属于stderr。我们可以将stderr信息重定向 到一个文件中,而stdout仍然保持不变。考虑如下代码:

$ cat a* 2> err.txt # stderr被重定向到err.txt a1
a1

   $ cat err.txt
   cat: a1: Permission denied

观察下面的代码:

   $ cmd 2>/dev/null

当对如果对stderrstdout进行重定向,被重定向的文本会传入文件。因为文本 已经被重定向到文件中,也就没剩下什么东西可以通过管道(|)传给接下来的命令, 而这些命令是通过stdin进行接收的。

 

(5)但是有一个方法既可以将数据重定向到文件,还可以提供一份重定向数据的副本作 为后续命令的stdin。这一切都可以使用tee来实现。举个例子:要在终端中打印 stdout,同时将它重定向到一个文件中,那么可以这样使用tee:

   command | tee FILE1 FILE2

在下面的代码中,tee命令接收到来自stdin的数据。它将stdout的一份副本写入 文件out.txt,同时将另一份副本作为后续命令的stdin。命令cat -n将从stdin中接 收到的每一行数据前加上行号并写入stdout:

   $ cat a* | tee out.txt | cat -n
   cat: a1: Permission denied

1a1 2a1

查看out.txt的内容:

   $ cat out.txt
   a1
   a1

注意,cat: a1: Permission denied 并没有在文件内容中出现。这是因为这些 信息属于stderr,而tee只能从stdin中读取。

默认情况下,tee命令会将文件覆盖,但它提供了一个-a选项,用于追加内容。例

如:$ cat a* | tee -a out.txt | cat –n。 带有参数的命令可以写成:command FILE1 FILE2...或者就简单的使用comman FILE

(7)我们可以使用stdin作为命令参数。只需要将-作为命令的文件名参数即可:

   $ cmd1 | cmd2 | cmd -

例如:

   $ echo who is this | tee -
   who is this
   who is this

也可以将 /dev/stdin作为输出文件名来代替stdin
类似地,使用 /dev/stderr代表标准错误,/dev/stdout代表标准输出。这些特殊的设备

文件分别对应stdinstderrstdout

 

 

3. 自定义文件描述符
文件描述符是一种用于访问文件的抽象指示器(abstract indicator)。存取文件离不开被称为

“文件描述符”的特殊数字。012分别是stdinstdoutstderr的预留描述符编号。 我们可以使用exec命令创建自己的文件描述符。如果你对用其他编程语言进行文件编程非

常熟悉,你可能已经注意到了文件打开模式。通常会用到3种模式。

只读模式。
截断写入模式。 追加写入模式。

< 操作符用于从文件中读取至stdin> 操作符用于截断模式的文件写入(数据在目标文件 内容被截断之后写入)。>>操作符用于追加模式的文件写入。(数据被添加到文件的现有内容中, 而且该目标文件中原有的内容不会丢失。)文件描述符可以用以上三种模式中的任意一种来创建。

  创建一个文件描述符进行文件读取:

$ 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 #打开文件进行写入 例如:

    $ exec 4>output.txt
    $ echo newline >&4
    $ cat output.txt
    newline

创建一个文件描述符用于写入(追加模式):

    $ exec 5>>input.txt

例如:

    $ exec 5>>input.txt
    $ echo appended line >&5
    $ cat input.txt
    newline
 

 

 

 

 

 

 

posted @ 2018-08-15 14:49  yunchong1019  阅读(484)  评论(0编辑  收藏  举报