在管道到另一个命令之前完全缓冲命令输出?

Jos*_*ica 16 shell pipe buffer

有没有办法只在没有临时文件的情况下执行另一个命令?我有一个运行时间更长的命令和另一个用于格式化输出并使用 curl 将其发送到 HTTP 服务器的命令。如果我只是执行commandA | commandBcommandB将启动curl,连接到服务器并开始发送数据。因为commandA时间太长,HTTP 服务器会超时。我可以随心所欲commandA > /tmp/file && commandB </tmp/file && rm -f /tmp/file

出于好奇,我想知道是否有办法在没有临时文件的情况下做到这一点。我试过了,mbuffer -m 20M -q -P 100但卷曲过程仍然从一开始就开始了。Mbuffer 等待直到commandA实际发送数据完成。(数据本身最多只有几百 kb)

G-M*_*ca' 15

这类似于其他几个答案。如果你有“moreutils”包,你应该有sponge命令。尝试

commandA | sponge | { IFS= read -r x; { printf "%s\n" "$x"; cat; } | commandB; }
Run Code Online (Sandbox Code Playgroud)

sponge命令基本上是一个传递过滤器(如cat),除了它在读取整个输入之前不会开始写入输出。即,它“吸收”数据,然后在您挤压它时释放它(就像海绵一样)。所以,在某种程度上,这是“作弊”——如果数据量很大,sponge几乎肯定会使用临时文件。但它对你来说是不可见的;您不必担心诸如选择唯一文件名和事后清理之类的日常事务。

{ IFS= read -r x; { printf "%s\n" "$x"; cat; } | commandB; } 读取输出的第一行sponge。请记住,这commandA在完成之前不会出现。  然后它启动commandB,将第一行写入管道,并调用cat以读取输出的其余部分并将其写入管道。


cuo*_*glm 5

管道中的命令是并发启动的,您需要将commandA输出存储在某个地方以备后用。您可以通过使用变量来避免临时文件:

output=$(command A; echo A)
printf '%s' "${output%%A}" | commandB
Run Code Online (Sandbox Code Playgroud)

  • @DigitalTrauma:它可以防止命令替换剥离尾随的换行符。 (3认同)