【问题标题】:pipe is returning empty string in bash in git for windows管道在 git for windows 中的 bash 中返回空字符串
【发布时间】:2016-10-05 05:34:31
【问题描述】:

编辑:更新到 Git for Windows >= 2.9.0.windows1 后问题已解决


免责声明

一些 cmets 指的是这个问题背后的完整“故事”,但我决定缩短它,因为它变得太长且难以理解。我向您展示尽可能简洁的失败示例。对于那些有兴趣了解问题的完整背景的人:可以在previous revision of the question 获得。


This:basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") 是安装 CLI 附带的任何软件包后由 npm 生成脚本中的第一行(不包括 hashbang)。 出于某种原因,basedir 解析不正确,这就是节点找不到模块并崩溃的原因。我设法将问题缩小到最新 Git for Windows 的 git-bash 上的子外壳中的管道。执行:

echo -n "1:"
echo "a" | cat
echo -n "2:"
echo "$(echo "a" | cat)"
echo -n "3:"
echo "$(echo "a")"

打印:

1:a
2:
3:a

我找不到其他人遇到这个问题,所以我认为这是我的环境(Windows 10 Pro,Git for Windows 2.8.4)有问题,我个人不知道它可能来自哪里。 我的发现:

  • 将适用于 Windows 的 Git 降级到 2.6.4 可以解决此问题。我仍然不喜欢被困在旧版本上;/
  • 它在干净的 Windows 10 虚拟机上运行良好
  • 管道输出似乎完全为空,因为在 sn-p 之后运行不会返回任何结果。
  • 在全新安装 mingw + msys 时不会出现问题

sn-p:

echo $(echo foobar | cat > bazzzzzzzzzz ; ) ; cat bazzzzzzzzzz
find /c -name bazzzzzzz* 2> /dev/null # /c, /d and /x are my Windows partitions
find /d -name bazzzzzzz* 2> /dev/null # I did test if it actually works for existing file and it does
find /x -name bazzzzzzz* 2> /dev/null

感谢 agc 为解决这一问题提供的宝贵帮助。


我的PATH 变量如下所示:

PATH=/c/Users/ja/bin:/mingw64/bin:/usr/local/bin:/usr/bin:/bin:/mingw64/bin:/usr/bin:/c/Users/ja/bin:/c/Windows:/c/Windows/System32:/c/Windows/System32/Wbem:/c/Windows/System32/WindowsPowerShell/v1.0:/c/Program Files/nodejs:/c/ProgramData/Oracle/Java/javapath:/c/program files/graphicsmagick-1.3.23-q16:/c/ProgramData/chocolatey/lib/getopt/binaries:/c/Program Files (x86)/Windows Kits/8.1/Windows Performance Toolkit:/c/Program Files/nodejs:/c/Program Files (x86)/Microsoft VS Code/bin:/c/Users/ja/AppData/Roaming/npm:/c/Program Files (x86)/MacType:/usr/bin/vendor_perl:/usr/bin/core_perl

还有

$ which sed
/usr/bin/sed
$ which echo
/usr/bin/echo
$ which cat
/usr/bin/cat
$ echo $SHELL
/usr/bin/bash

【问题讨论】:

  • 在这种情况下确实不需要它,但正如我所说,这个脚本是在通过 npm 安装节点包的过程中自动生成的,所以每次安装后手动修改这些脚本几乎会破坏使用包管理器的想法。我还从问题的潜在来源中排除了 npm,因为我在互联网上找不到任何人在为此类问题苦苦挣扎。感谢您的评论:)
  • 它的行为好像不是调用普通的sed,而是调用sed -n,即,一个不打印任何内容的 sed 版本,除非明确告诉打印某些东西(或者只是一个完全损坏的命令,总是什么都不打印)。
  • 尝试将echo "$0" | sed -e 's,\\,/,g' 换成echo "$0" | tr '\\' '/'
  • 两个错误都有$( foo | bar )之类的东西,所以下一步是看看你是否可以简化它。 $( foo ) 单独工作吗?如果是这样,可能是管道,所以试试$( foo | cat )
  • 好的,所以我们知道 pipe 的工作,简单的 命令替换 工作,但是 命令替换pipe 失败——或者可能将输出发送到 STDOUT 以外的某个地方。要测试,请尝试echo $(echo foobar | cat > baz ; ) ; cat baz

标签: windows git bash shell pipe


【解决方案1】:

总结 cmets,短 (tl;dr) 版本:降级、升级和/或重新安装 Git for Windows 附带的 MSYS 和 MinGW。

MSYS补充MinGWGit for Windows提供的版本可能会从MSYS的原始维护者那里修改。 a bug reported against MSYS 似乎是同样的问题(使用“mingw 版本:64 位与 git 版本 2.8.3.windows.1 捆绑在一起”),但被标记为“适合我”(即“可以” t 重现”)。但是有评论说问题可能出在重新包装上:

“请注意,与 git for windows 捆绑在一起的 MSYS 可能会从我们的官方发行版中进行修改,(并且 64 位 MinGW 当然不是我们的);因此我们不正式支持其中任何一个。” https://sourceforge.net/p/mingw/bugs/2303/

长话短说,看起来像一个错误。

【讨论】:

    【解决方案2】:
    basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
    

    这似乎是XY problem 的一个例子。让我们分解这一行:

    echo "$0"
    

    这通常是脚本的路径,例如./alfa.sh

    sed -e 's,\\,/,g'
    

    这会将反斜杠替换为正斜杠。这是这条线的起点 分崩离析:

    1. 你不需要-e,你可以直接sed 's,\\,/,g'

    2. 您可能不需要g,通常只需一个斜线,如图所示 以上

    3. 更改斜线没有任何意义。 Bash,即使在 Windows 上,也是 已经使用正斜杠了

    4. 如果由于某种原因确实需要更改斜线,则 Sed 不是正确的 无论如何,cygpath 的工具是:

      $ cygpath -m 'C:\Program Files\Mozilla Firefox\firefox.exe'
      C:/Program Files/Mozilla Firefox/firefox.exe
      
    dirname
    

    现在您在 sed/cygpath 之后调用 dirname。它应该在之前调用,即 sed/cygpath 的方式不必更换太多:

    basedir=$(cygpath -m "$(dirname "$0")")
    

    最后,sed 命令不好还有另一个原因;如果你要成为 吐出一条路,应该是绝对的,为什么不呢?

    basedir=$(cygpath -am "$(dirname "$0")")
    

    现在请注意,甚至不涉及管道。我还要补充一点,这个问题是 introduced recently 到 NPM 仓库。您可以向那里的开发人员发表评论。

    【讨论】:

    • 感谢您提供如此冗长的回答,但正如我之前提到的:这些脚本是由 npm 生成。您提出的是解决方法 - 不使用管道。如果不手动编辑每个生成的脚本,我根本无法做到这一点。我要的是提示/线索/想法,说明为什么这些脚本不能在我的机器上运行。在 stackoverflow 社区的帮助下,我设法将问题的范围缩小到子shell 中。这就是为什么我认为这不是 XY 问题。另外,我并不否认 sed 在这里的使用至少是有问题的 :)
    • 虽然我知道在这些脚本中使用 pipe 和 sed 可能是不恰当的,但事实是它对其他所有人都适用。我在尝试执行 npm 包时偶然发现了这一点,但它更通用,因为它可能会破坏在我的机器上评估的每个 sh 脚本,而 npm 与此无关。如果我要找到问题的根源,我会去 Git for Windows 存储库,但它仍然可以在干净的 VM 上工作,所以我认为猜测潜在原因的任务不适合他们的问题跟踪器。询问 SO 社区似乎是一个更好的选择
    • @bgoscinski 您还没有提供一个需要管道的有效示例。 cat 在您的第一个示例中是 NOOP,sed 示例可以通过 cygpath 放弃管道进行重新设计。如果你想要一个答案举一个实际需要管道的例子。只是说“我想要这个,因为我想要它”并不时髦
    • 我不想这样做,因为 npm 或 any 其他类似的脚本会在我的机器上失败。还不够吗?
    • @Sierra,管道不起作用本身比管道边界的代码更有趣。实际上,这更像是一个 XY(Z) 问题,其中 XY 导致发现 Z,之后 XY 都被 Z 相形见绌。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-04-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-16
    • 2020-03-30
    相关资源
    最近更新 更多