在 windows 上试用 gzip 遇到个管道的坑。
windows 上是没有 gzip 命令的。
首先安装 scoop install gzip
压缩命令一般这么写 cat script.ps1|gzip >script.gz
这个写法在 bash zsh 和 cmd 都能正常工作,但是 pwsh 不行,甚至 powershell 5 也不行。
我知道 ps 管道可以传 PS-Object,但不会不会兼容文件流吧,目前还没找到说这个问题的,先在这分享一下继续寻找 解决方案。
1
Tumblr 2020-07-29 13:55:07 +08:00
🤦♂️ 在 PowerShell 中,cat 是 Get-Content 的 alias,获取出来的是按行分割的数组;
管道传递的时候,是一个元素一个元素地传递,这样写肯定不行了。 |
3
ghostwwg 2020-07-29 14:09:34 +08:00
木有问题啊。。。
|
4
ghostwwg 2020-07-29 14:09:53 +08:00
indows PowerShell
版权所有 (C) Microsoft Corporation 。保留所有权利。 尝试新的跨平台 PowerShell https://aka.ms/pscore6 PS C:\Users\ghost> cat .\testpage|gzip > aaa.gz PS C:\Users\ghost> ls .\aaa.gz 目录: C:\Users\ghost Mode LastWriteTime Length Name ---- ------------- ------ ---- -a---- 2020/7/29 14:09 56 aaa.gz PS C:\Users\ghost> |
5
geelaw 2020-07-29 14:17:36 +08:00 1
楼主的遇到的问题是多重问题,第一步 cat 就已经错了,因为它会以文本读取文件,而不是复制二进制流。
第二步管道传入 gzip 也错误,因为经过 PowerShell 的外部程序管道都会经过文本的转换。 第三步保存到文件也错误,因为这个操作也会按照文本解读,还会进行编码转换。 正确解法是使用 Start-Process 来重定向,但是这只能解决输入输出都是文件的简单情况。 那么 PowerShell 使用二进制管道的正解是什么呢?这里臭不要脸地推荐我写的 module Use-RawPipeline,专门解决 PowerShell 二进制管道交互问题,且在 Windows 上以性能最佳的方式实现。 GitHub 链接: https://github.com/GeeLaw/PowerShellThingies/tree/master/modules/Use-RawPipeline 博客: https://geelaw.blog/entries/powershell-use-rawpipeline/ @ghostwwg #4 有文件出现不代表文件内容是对的。 |
6
ColinZeb OP |
8
geelaw 2020-07-29 21:04:50 +08:00 via iPhone 1
@ColinZeb #6 bash 不支持“文本重定向”,它对文本没有概念,管道是二进制流。至于 cat,那是一个外部程序,它也不懂“文本”的概念,只是负责把多个文件粘在一起。举个例子,当你 cat 多个用 UTF 编码的文本文件时,结果不会得到统一的编码,也不会删除多余的 BOM 。
PowerShell 没有特别想要兼容其他 shell 的用法,而且管道传输对象本来就和大多数 shell 不兼容。 |
9
hez2010 2022-03-05 19:45:19 +08:00
这是一个古老的问题: https://github.com/PowerShell/PowerShell/issues/1908 ,PowerShell 的 > 会把东西转换成文本导致原数据被破坏,只不过因为为了兼容性一直没有进行这个破坏性更改。
另外 PowerShell 的 cat 也是默认转换成字符串数组,要用 Get-Content -AsByteStream xxx 或者 cat -AsByteStream xxx 才能获取到源数据。 不过下一个版本 PowerShell 7.3 应该会给出解决方案。 |