【问题标题】:Redirect output from file to stdout将输出从文件重定向到标准输出
【发布时间】:2015-08-31 23:19:28
【问题描述】:

我有一个程序只能将其结果输出到文件,带有-o 选项。这次我需要将它输出到控制台,即stdout。这是我的第一次尝试:

myprog -o /dev/stdout input_file

但它说:

/dev/ 不可写

我发现this question 和我的很相似,但是/dev/stdout 如果没有一些额外的魔法显然是行不通的。

问:如何将输出从文件重定向到stdout

附:没有任何专门软件的常规方法更可取。

【问题讨论】:

  • 你能告诉我们你的程序的来源,你在哪里输出吗?
  • @Samuel,程序不是我写的。实际上是texi2html,我猜它的源代码是可用的,但我怀疑那里有错误。
  • @TomFenech,输出到文件,该文件的名称是通过将 .texi 扩展名替换为 .html 扩展名而产生的。它只是尝试猜测输出文件的名称。
  • 你可以试试myprog -o - input_file。通常- 被解释为标准输入/标准输出,但这取决于程序并且不是外壳的一部分。
  • @Samuel,这个操作根据定义不需要root权限。我的意思是,即使是普通用户也应该能够将输出重定向到屏幕。

标签: bash shell unix stdout


【解决方案1】:

许多工具将- 解释为标准输入/标准输出,具体取决于其使用上下文。不过,这不是 shell 的一部分,因此取决于所使用的程序。

在您的情况下,以下可以解决您的问题:

myprog -o - input_file

【讨论】:

    【解决方案2】:

    如果程序只能写入文件,那么您可以使用命名管道:

    pipename=/tmp/mypipe.$$
    mkfifo "$pipename"
    
    ./myprog -o "$pipename" &
    
    while read line
    do
        echo "output from myprog: $line"
    done < "$pipename"
    
    rm "$pipename"
    

    首先我们创建管道,我们将它放入/tmp 以防止它影响备份程序。 $$ 是我们的 PID,使名称在运行时唯一。

    我们在后台运行程序,它应该阻止尝试写入管道。一些程序使用一种称为“内存映射”的技术,在这种情况下这会失败,因为管道不能被内存映射(一个好的程序会检查这个)。

    然后我们像读取任何其他文件一样读取脚本中的管道。

    最后我们删除管道。

    【讨论】:

    • @Rambo Ramon:我应该指出,直到我发布此帖子后,我才看到您对 scottgwald 帖子的评论。你写的时候我正在测试代码!
    • 没问题。使用命名管道获得完整的答案很好,因为它比我的答案更通用。接受我的投票:)
    • 这可能会失败,至少有两个原因。首先,如果myprog 在打开目标文件之前将其删除;实际上似乎是这样,因为-o /dev/stdout 返回错误/dev/ not writable。第二,如果myprog需要通过输出文件lseek();这不是很常见,但肯定会发生。
    • @lcd047:同意。从根本上说,我们确实需要更多地了解该计划。如果使用了lseek(),那么接受的答案将不起作用(与mmap() 相同),但如果输出文件为-,它可能只是进入不同的分支。惊讶的是不在程序的文档中。 :-)
    【解决方案3】:

    你可以catmyprog写的文件内容。

    myprog -o tmpfile input_file &amp;&amp; cat tmpfile

    这将产生所描述的效果 - 允许您将 myprog 的输出通过管道传输到一些后续命令 - 尽管它是一种与您预想的不同的方法。

    myprog(可能更贴切notmyprog)的输出太大而无法写入磁盘的情况下,这种方法并不好。

    清理同一行中的临时文件并在最后仍然通过管道输出内容的解决方案是这样的

    myprog -o tmpfile input_file &amp;&amp; contents=`cat tmpfile` &amp;&amp; rm tmpfile &amp;&amp; echo "$contents"

    它将文件的内容存储在一个变量中,以便在删除文件后可以访问它。注意echo 命令的参数中的引号。这些对于在文件内容中保留换行符很重要。

    【讨论】:

    • 这可能是一种黑客行为。如果重定向是不可能的,这绝对是可行的方法,但我应该注意它不能回答问题。
    • 要将其视为一个答案,您至少应该提供之后删除临时文件的代码。除此之外,我建议使用命名管道而不是普通文件。
    • @scottgwald re "在大多数正常情况下都没有关系" ,不知道 myprog 做了什么,我们不知道什么是正常的。例如:如果整点是输出对于磁盘上的文件来说太大了,并且我们正在重定向以便可以在写入时使用它,那么临时文件是无用的。
    • @ckhan 点。 cdarke 的回答实际上可以解决问题,我不熟悉命名管道。
    • 为您辩护,如果程序使用内存映射文件,那么这是迄今为止发布的唯一可行的解​​决方案。显然,在这种情况下它不能使用mmap,因为接受的答案也不起作用(无论如何,使用mmap 创建和写入整个文件都很棘手)。