临时数据的伪文件

hig*_*guy 123 bash pipe files

我经常想将相对较短的字符串数据(虽然可能是几行)提供给命令行程序,这些程序只以重复的方式接受来自文件(例如 wdiff)的输入。当然我可以创建一个或多个临时文件,将字符串保存在那里,然后以文件名作为参数运行命令。但在我看来,如果数据实际写入磁盘,则此过程的效率会非常低,而且如果我多次重复此过程(例如,如果我想提供单行长文本),它可能会对磁盘造成不必要的伤害文件到 wdiff。有没有推荐的方法来规避这种情况,比如通过使用诸如管道之类的伪文件来临时存储数据而不实际将其写入磁盘(或仅在超过临界长度时才将其写入)。请注意, wdiff 有两个参数,并且,wdiff <"text".

Mec*_*ail 175

在 Bash 中,您可以使用command1 <( command0 )重定向语法,它重定向command0的标准输出并将其传递给command1将文件名作为命令行参数的 a。这称为进程替换

一些采用文件名命令行参数的程序实际上需要一个真正的随机访问文件,因此这种技术不适用于那些。但是,它适用于wdiff

user@host:/path$ wdiff <( echo hello; echo hello1 ) <( echo hello; echo hello2 )
hello
[-hello1-]
{+hello2+}
Run Code Online (Sandbox Code Playgroud)

在后台,这会创建一个 FIFO,<( )将 FIFO内部的命令通过管道传输到 FIFO,并将 FIFO 的文件描述符作为参数传递。要查看发生了什么,请尝试使用它 withecho打印参数而不对其进行任何操作:

user@host:/path$ echo <( echo hello )
/dev/fd/63
Run Code Online (Sandbox Code Playgroud)

创建命名管道更灵活(如果您想使用多个进程编写复杂的重定向逻辑),但对于许多目的来说这已经足够了,而且显然更易于使用。

>( )当您想将其用作输出时,还有语法,例如

$ someprogram --logfile >( gzip > out.log.gz )
Run Code Online (Sandbox Code Playgroud)

另请参阅bash 手册页“进程替换”部分Bash 重定向备忘单以了解相关技术。

  • ksh 发明了这个。您正在使用不支持它的 * 变体 * ksh (7认同)
  • _某些采用文件名命令行参数的程序实际上需要一个真正的随机访问文件,因此该技术不适用于那些。_ 在这些情况下你会做什么。例如`ssh -F &lt;(vagrant ssh-config) default`会非常好,但可惜。 (2认同)

gol*_*cks 67

使用命名管道。举例说明:

mkfifo fifo
echo -e "hello world\nnext line\nline 3" > fifo
Run Code Online (Sandbox Code Playgroud)

-e告诉回声正确解读换行符逃生(\n)。这将阻塞,即您的外壳将挂起,直到某些东西从管道中读取数据。

在同一目录中的某处打开另一个 shell:

cat fifo
Run Code Online (Sandbox Code Playgroud)

您将读取 echo,它将释放另一个 shell。尽管管道作为磁盘上的文件节点存在,但通过它的数据并不存在;这一切都发生在记忆中。您可以背景 ( &) 回声。

管道有一个 64k 缓冲区(在 linux 上),并且像套接字一样,在写满时会阻塞写入器,因此只要您不过早地杀死写入器,就不会丢失数据。

  • `/tmp` 在大多数发行版中被配置为使用内存中的 `tmpfs` 文件系统。当您在 /tmp 中写入文件时,它会直接进入您的 RAM,这对于必须快速访问并多次重写的半弹性文件来说是一个很好的答案。 (3认同)

小智 13

wdiff 是一个特殊情况,因为它需要 2 个文件名参数,但是对于所有只需要 1 个参数并且顽固地拒绝接受文件名参数以外的任何命令的所有命令,有两个选项:

  • 文件名“-”(即减号)在大约 1/2 的时间内起作用。这似乎取决于所讨论的命令以及命令的开发人员是否会捕获该案例并按预期处理它。例如

    $> ls | 猫 -

  • linux 中存在一个名为 /dev/stdin 的伪文件,如果命令绝对需要文件名,则可以使用该文件。这更有可能起作用,因为它不需要从命令中进行任何特殊的文件名处理。如果 fifo 有效,或者 bash进程替换方法有效,那么这也应该有效,并且不是特定于 shell 的。例如

    $> ls | 猫/开发/标准输入