在 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.
Unix
和 PowerShell
管道的操作方式相同。您可能会看到 Unix
与 PowerShell
之间存在差异的原因是它们处理问题的方式不同。
Unix
在命令之间传递 Strings
。 Powershell
管道将在命令之间传递 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
管道。
我的命令行是这样的(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.
Unix
和 PowerShell
管道的操作方式相同。您可能会看到 Unix
与 PowerShell
之间存在差异的原因是它们处理问题的方式不同。
Unix
在命令之间传递 Strings
。 Powershell
管道将在命令之间传递 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
管道。