• 玩转文件描述符及重定向


    返回主页面

    文件描述符是与文件输入、输出相关联的整数。它们用来跟踪已打开的文件。最常见的文件 描述符是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
    
     
  • 相关阅读:
    .NET Windows服务开发流程
    SQL Server 动态行转列(参数化表名、分组列、行转列字段、字段值)
    SQL触发器批量删除数据库中的表
    如何使用Chrome Timeline 工具(译)
    修复运行 tasklist 命令时提示 ERROR: Not found
    删除坏掉的 Active Directory Domain
    为 WSUS 服务器定期运行清理向导
    为 Exchange 服务器编写自定义的反垃圾插件
    Windows 10 下安装 npm 后全局 node_modules 和 npm-cache 文件夹的设置
    在 Win10 命令行使用 Consolas + 微软雅黑
  • 原文地址:https://www.cnblogs.com/tianzhiyun/p/9481356.html
Copyright © 2020-2023  润新知