在 windows 上通过管道使用 7-zip 压缩到 tar.xz

Compressing to tar.xz using 7-zip through a pipe on windows

我的命令行是这样的(powershell):

z ="`"c:\Program Files-Zipz.exe`""
&z a -r -ttar -bd -so . | &z a -r -txz -bd $archive -si

生成的存档文件确实包含一个 tar 文件,但那个 tar 文件已损坏。

请注意,将管道分成两个命令可以正常工作:

&z a -r -ttar -bd ${archive}.tmp .
&z a -r -txz -bd $archive ${archive}.tmp

生成的存档完全有效。

那么,我的管道出了什么问题?

(我正在使用 Powershell)

您的管道没有任何问题,是管道的工作方式导致了错误。

PowerShell 管道以异步方式工作。这意味着即使第一个命令尚未完成执行,第一个命令的输出也可立即用于第二个命令的对象,See here.

UnixPowerShell 管道的操作方式相同。您可能会看到 UnixPowerShell 之间存在差异的原因是它们处理问题的方式不同。

Unix 在命令之间传递 StringsPowershell 管道将在命令之间传递 full-fledged .net object。命令之间过去的数据类型的这种差异将是它在 unix 而不是 PowerShell 上工作的原因。如果 7z.exe 不能正确地压缩这些 .net objects 文件将会损坏,See here

尝试在管道之间添加 | %{ "$_" },例如

&z a -r -ttar -bd -so . | %{ "$_" } | &z a -r -txz -bd $archive -si

关键是第二次调用 7z 需要 STDIN 上的未修改数据,但 PowerShell 正在将第一次调用的输出转换为 7z到(多个)(字符串)对象。 %foreach-object 的别名,因此附加命令的作用是遍历每个对象并将其转换为纯字符串,然后再传递给对 7z 的第二次调用。

编辑: 通读 PowerShell’s Object Pipeline Corrupts Piped Binary Data 现在看来我的建议似乎行不通,而且也没有办法修复它。好吧,除了将整个管道包装到一个 cmd /c "..." 调用中以使 cmd 而不是 PowerShell 处理管道。

Edit2: 我也在尝试 this solution PowerShell Cookbook,但是速度很慢。

最后,我创建了一个 .cmd 脚本,其中包含我从 PowerShell 脚本调用的 7z 管道。