V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
ColinZeb
V2EX  ›  PowerShell

Powershell 的管道兼容性

  •  
  •   ColinZeb · 2020-07-29 13:44:31 +08:00 · 3461 次点击
    这是一个创建于 1339 天前的主题,其中的信息可能已经有所发展或是发生改变。

    在 windows 上试用 gzip 遇到个管道的坑。

    windows 上是没有 gzip 命令的。

    首先安装 scoop install gzip

    压缩命令一般这么写 cat script.ps1|gzip >script.gz

    这个写法在 bash zsh 和 cmd 都能正常工作,但是 pwsh 不行,甚至 powershell 5 也不行。

    我知道 ps 管道可以传 PS-Object,但不会不会兼容文件流吧,目前还没找到说这个问题的,先在这分享一下继续寻找 解决方案。

    9 条回复    2022-03-05 19:45:19 +08:00
    Tumblr
        1
    Tumblr  
       2020-07-29 13:55:07 +08:00
    🤦‍♂️ 在 PowerShell 中,cat 是 Get-Content 的 alias,获取出来的是按行分割的数组;
    管道传递的时候,是一个元素一个元素地传递,这样写肯定不行了。
    ColinZeb
        2
    ColinZeb  
    OP
       2020-07-29 13:58:18 +08:00
    @Tumblr 不是 cat 的问题,换成 wsl cat 也一样的
    ghostwwg
        3
    ghostwwg  
       2020-07-29 14:09:34 +08:00
    木有问题啊。。。
    ghostwwg
        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>
    geelaw
        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 有文件出现不代表文件内容是对的。
    ColinZeb
        6
    ColinZeb  
    OP
       2020-07-29 14:36:52 +08:00
    @ghostwwg 打开文件试试。
    @geelaw bash 环境里的 cat 支持文本文件和二进制文件重定向到管道,我以为 pwsh 会兼容
    LokiSharp
        7
    LokiSharp  
       2020-07-29 14:47:39 +08:00
    @ColinZeb #6 pwsh 传的是对象,不是文本。。。
    geelaw
        8
    geelaw  
       2020-07-29 21:04:50 +08:00 via iPhone   ❤️ 1
    @ColinZeb #6 bash 不支持“文本重定向”,它对文本没有概念,管道是二进制流。至于 cat,那是一个外部程序,它也不懂“文本”的概念,只是负责把多个文件粘在一起。举个例子,当你 cat 多个用 UTF 编码的文本文件时,结果不会得到统一的编码,也不会删除多余的 BOM 。

    PowerShell 没有特别想要兼容其他 shell 的用法,而且管道传输对象本来就和大多数 shell 不兼容。
    hez2010
        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 应该会给出解决方案。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3073 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 10:59 · PVG 18:59 · LAX 03:59 · JFK 06:59
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.