如何在没有中间文件的情况下将多个命令的结果和管道连接到另一个?

fdm*_*ion 1 pipe shell-script xz

假设我有四个非常大的文本文件,都用 xz 压缩。

file1.log.xz
file2.log.xz
file3.log.xz
file4.log.xz
Run Code Online (Sandbox Code Playgroud)

我想做的是将这四个文件的未压缩内容连接成一个新文件file.xz。问题是,我希望不必通过中间文件。

这些文件是非常大的日志文件,大小为千兆字节。压缩后,它们小于 100MB,但如果我要扩展所有四个文件然后重新连接,我至少需要 30GB 的存储空间来存储未压缩的文件。当然,我可以将cat所有未压缩的文件xz重新压缩:

cat file1.log file2.log file3.log file4.log | xz -ve9 - > newfile.log.xz
Run Code Online (Sandbox Code Playgroud)

我知道如何在没有中间件的情况下在命令行中连接两个文件,假设一个未压缩,一个已压缩:

xz -d -c file2.log.xz | cat file1.log - | xz -ve9 - > files1and2.log.xz
Run Code Online (Sandbox Code Playgroud)

但这仅适用于一个文件,其中之一必须已经解压缩。

我不确定我是否可以cat将各种 .xz 文件放在一起 - 让我们假设它们可能已经用不同的参数进行了压缩。

在更高的层次上,可以问这个问题本身:您能否获取多个(超过两个)命令的输出,连接这些输出,并将它们通过管道传输到另一个进程而无需中间文件?(假设场景:假设我正在使用输出到 stdout 的脚本对所有四个非常大的文件进行某种处理,并希望将输出放入另一个压缩文件中。)

是否可以仅使用 shell 命令来执行此操作?

Ste*_*itt 5

xz文件说,

可以按.xz原样连接文件。 xz将解压缩这些文件,就好像它们是单个.xz文件一样。

从我的测试来看,即使使用不同的选项压缩不同的文件,这也有效;所以在你的情况下

cat -- *.log.xz > newfile.log.xz
Run Code Online (Sandbox Code Playgroud)

会正常工作。

要回答更一般的问题,您可以通过管道传输复合命令的输出,例如

for file in -- *.log.xz; do xzcat -- "$file"; done | xz -ve9 > newfile.log.xz
Run Code Online (Sandbox Code Playgroud)

或任何子外壳。这将允许您在重新压缩日志文件之前对其进行任何处理。但是,在基本情况下,这也不是必需的;您可以通过运行来解压缩和重新压缩所有文件

xzcat -- *.log.xz | xz -ve9 > newfile.log.xz
Run Code Online (Sandbox Code Playgroud)

如果您添加-f它甚至适用于未压缩的文件,那么

xzcat -f -- uncompressed.log *.log.xz | xz -ve9 > newfile.log.xz
Run Code Online (Sandbox Code Playgroud)

将允许您组合未压缩和压缩的日志。