POSIX“tee”命令如何工作?

2024-01-16

tee newOutputFile < existingInputFile > newOutputFile2

究竟会怎样tee接受论点?会是这样吗?

  1. Tee将首先处理newOutputFile < existingInputFile所以existingInputFile的内容将被写入newOutputFile
  2. newOutputFile > newOutputFile2所以newOutputFile的内容会被写入newOutputFile 2

我正在尝试编写一个 shell 来处理这个特定的命令。但是,我对将参数传递给哪个顺序感到困惑tee。我编写程序的方式就可以了

tee newOutputFile2 < existingInputFIle


The tee命令是一个常规的 Unix 程序,就像sh or sort or cat.

处理涉及的所有 I/O 重定向工作< existingInputFile and > newOutputFile2是由 shell 之前完成的tee命令被调用(之后fork创建将执行的进程tee命令)。该命令是通过其标准输入来调用的existingInputFile其标准输出为newOutputFile2。给出的唯一论据是tee are argv[0](字符串tee) and argv[1](字符串newOutputFile),加上一个空指针来标记参数列表的末尾。

特别注意,shell不参与实际读取existingInputFile;它只是打开它进行读取并将其连接到标准输入tee,但不知道是否tee命令实际上是否读取它。同样,shell 也不参与实际写入newOutputFile2;它只是打开并截断它(或创建它)并将其连接到标准输出tee,但不知道是否tee命令实际上向其中写入任何内容。在此背景下,虽然tee命令运行时,父 shell 完全是被动的,不执行任何 I/O。

通过设计,tee读取其标准输入,并将所有内容的一份副本写入其参数列表中给出的每个文件,并将另一份副本写入标准输出。


我的印象是 shell 参与了文件的实际读写。所以当我打电话时execvp,它只接受命令(在本例中tee)以及将内容写入的最终文件(在本例中newOutputFile2)。我正在尝试创建自己的 shell 程序,我将如何进行 I/O 重定向。这是哪里吗dup2发挥作用吗?

shell只参与文件的打开和关闭,不参与文件的读写。在你的命令行中tee newOutputFile < existingInputFile > newOutputFile2,命令是tee唯一的另一个论点是newOutputFile。一般来说,命令(tee在这种情况下)不知道为其提供标准输入的文件的名称,也不知道它在标准输出上写入的文件的名称。确实,尤其是与tee,输入通常是管道而不是文件,并且输出通常也是管道而不是文件:

some_command arg1 arg2 | tee some_command.log | another_command its_arg1 its_arg2 > output.file

在你自己的 shell 程序中,你可以使用dup2()复制您单独打开的文件描述符,使其成为标准输入:

// Redirect standard input from existingInputFile using dup2()
char *i_filename = "existingInputFile";
int fd = open(i_filename, O_RDONLY);
if (fd < 0)
{
    fprintf(stderr, "unable to open file %s for reading (%d: %s)\n",
            i_filename, errno, strerror(errno));
    exit(1);
}
dup2(fd, STDIN_FILENO);
close(fd);  // Crucial!

请注意,关闭很重要fd在这种情况下。否则,该命令将在至少打开一个未在命令行中指定的额外文件描述符的情况下运行。您将有一个用于标准输出重定向的类似代码块。

或者你可以使用:

// Redirect standard input from existingInputFile
close(0);
char *i_filename = "existingInputFile";
int fd = open(i_filename, O_RDONLY);
if (fd < 0)
{
    fprintf(stderr, "unable to open file %s for reading (%d: %s)\n",
            i_filename, errno, strerror(errno));
    exit(1);
}
assert(fd == 0);

// Redirect standard output to NewOutputFile2
close(1);
char * o_filename = "newOutputFile2";
fd = open(o_filename, O_WRONLY|O_CREAT|O_TRUNC, 0644); // Classically 0666
if (fd < 0)
{
    fprintf(stderr, "unable to open file %s for writing (%d: %s)\n",
            o_filename, errno, strerror(errno));
    exit(1);
}
assert(fd == 1);

这是因为open()返回先前未打开的最低可用文件描述符,因此通过关闭 0,您知道open()成功时返回 0,失败时返回 -1(即使 0 之前已关闭)。然后,通过归纳,你知道关闭 1 后,open()成功时返回 1,失败时返回 -1(即使 1 之前已关闭)。您通常不会修改标准错误,除非命令行包含 I/O 重定向,例如2>/dev/null or 2>&1或类似的东西。

如果您愿意,可以将 0644 写为:

O_IRUSR|O_IWUSR|O_IRGRP|O_IROTH

(并添加|O_IWGRP|O_IWOTH如果您想使用组和其他写入权限(0666);权限将被修改umask反正)。就我个人而言,我发现八进制更容易阅读,但我在几年前就开始使用八进制权限O_Ixyyy名字被发明了。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

POSIX“tee”命令如何工作? 的相关文章

  • 调用 cat 时 shell 脚本挂起

    我有一个 shell 脚本 它通过电子邮件向我发送通过 crontasks 遇到的错误 如下所示 exec gt output cat shopt s nocasematch if output error output warning t
  • Bash 参数引号和 eval

    我编写了一个 bash 日志记录库 用我公司当前正在使用的一些复杂脚本来实现 在进行日志调用时 我一直致力于提供调用脚本的脚本文件名 BASH SOURCE 和行号 LINENO 但是 我不想依赖用户或实现脚本来将这两个变量作为参数传递 如
  • 这种 bash 文件名提取技术有何用途?

    我有一部分 bash 脚本正在获取不带扩展名的文件名 但我试图了解这里到底发生了什么 是做什么用的 有人可以详细说明 bash 在幕后做了什么吗 如何在一般基础上使用该技术 bin bash for src in tif do txt sr
  • 发送/捕获 SIGTERM 的 Win32 API 模拟

    在 POSIX OS 下 有信号 API 允许向进程发送信号以将其关闭 使用kill 您可以使用sigaction捕获它并执行您需要的操作 然而 Win32不是POSIX系统 所以 如何处理可能出现的关闭事件 例如来自 任务管理器 中的 结
  • 为什么 shell=True 的 subprocess.Popen() 在 Linux 和 Windows 上的工作方式不同?

    使用时subprocess Popen args shell True 跑步 gcc version 仅作为示例 在 Windows 上我们得到 gt gt gt from subprocess import Popen gt gt gt
  • 使用运算符 j 操作 zsh 数组

    以下代码摘自here http eseth org 2010 git in zsh html function vi git st local ahead behind remote local a gitstatus Are we on
  • c 使用 lseek 以相反顺序复制文件

    我已经知道如何从一开始就将一个文件复制到另一个文件 但是我如何修改程序以按相反的顺序复制它 源文件应具有读取访问权限 目标文件应具有读写执行权限 我必须使用文件控制库 例如 FILE A File B should be ABCDEF FE
  • 在 Django shell 会话期间获取 SQL 查询计数

    有没有办法打印 Django ORM 在 Django shell 会话期间执行的原始 SQL 查询的数量 Django 调试工具栏已经提供了此类信息 例如 5 QUERIES in 5 83MS但如何从 shell 中获取它并不明显 您可
  • 如何在 Bash 中删除字符串的第一部分?

    该代码将给出第一部分 但是如何删除它并获取没有第一部分的整个字符串 echo first second third etc cut d f1 你应该看看info cut 这将解释什么f1 means 实际上我们只需要第二个字段之后的字段 f
  • 通过 shell 脚本查找“非”硬链接的文件

    给定一个目录 如何找到其中的所有文件 以及任何子目录 not硬链接文件 或者更具体地说 这不是具有多个引用的硬链接文件 基本上我想扫描一个文件夹并返回一个列表unique该目录中的文件 包括目录和符号链接 不是它们的目标 如果可能的话 最好
  • dlsym() + RTLD_NEXT 在 Ubuntu 20.04 上无法按预期工作

    使用时 我在 Ubuntu 20 04 gcc v 9 3 0 上遇到了奇怪的运行时行为dlsym call 请看下面一个简单的例子 文件测试 cpp include
  • 无法从 bash 脚本使用 nvm

    我正在尝试编写一个 shell 脚本来自动设置我的开发环境 安装 python nvm node mongo 等 我正在使用 nvm 来安装 Node js 它告诉您关闭并重新打开终端以开始使用 nmv 命令 我尝试获取 bashrc 和
  • Python 子进程:无法转义引号

    我知道以前曾问过类似的问题 但它们似乎都是通过重新设计参数的传递方式 即使用列表等 来解决的 但是 我这里有一个问题 因为我没有这个选项 有一个特定的命令行程序 我使用的是 Bash shell 我必须向其传递带引号的字符串 它不能不被引用
  • 如何在不使用 MacPorts 或 Fink 的情况下在 OS X Leopard 上安装 lxml?

    我过去曾多次尝试过此操作并遇到问题 有没有人有在没有 MacPorts 或 Fink 的情况下在 OS X 上安装 lxml 的方法 并且绝对有效 最好有完整的 1 2 3 步骤来下载和构建每个依赖项 感谢 Twitter 上的 jesse
  • 使用 hcitool 扫描低功耗蓝牙?

    当我运行此命令时 BLE 设备扫描仅持续 5 秒 sudo timeout 5s hcitool i hci0 lescan 输出显示在终端屏幕中 但是 当我将输出重定向到文件以保存广告设备的地址时 每次运行该命令时 我都会发现该文件是空的
  • 在 bash 中快速引用 stdout(即上一个命令的输出)?

    有没有办法快速 例如通过键盘快捷键等 引用写入到 stdout 的上一个命令的输出 例如 如果我这样做 which rails 它回来了 usr local bin rails然后我想在 textmate 中打开该文件 我可以像这样重新输入
  • 如何从命令行执行 PHP 代码?

    我想执行单个 PHP 语句 例如if function exists my func echo function exists 直接使用命令行 无需使用单独的 PHP 文件 这怎么可能 如果您要在命令行中执行 PHP 我建议您安装phpsh
  • ubuntu 中的 echo -e 选项不起作用

    我的同事使用Ubuntu 我使用openSUSE 我们使用相同的makefile编译相同的源代码 我的环境运行良好 但我的同事不能 总是输出无法识别 e选项 我们检查makefile 只发现echo命令使用 e option Ubuntu的
  • 如何按文件大小对查找结果进行排序

    如何按文件大小对 find 命令的结果进行排序 我试图对这个 find 命令的结果进行排序 find src type f print0 我不需要目录的大小 我需要仅按大小排序的文件相对路径 这是如何做的using find command
  • Bash shell 读取错误:0:资源暂时不可用

    编写 bash 脚本时 有时你运行的命令会打开另一个程序 例如 npm composer 等 但同时你需要使用read以提示用户 你不可避免地会遇到这种错误 read read error 0 Resource temporarily un

随机推荐