当来自 Windows PowerShell 的 运行 node.js 脚本时,参数转义未正确解释

Argument escaping not interpreted correctly when running node.js script from Windows PowerShell

给定以下脚本:

const yargs = require('yargs');

const argv =
    yargs
        .usage('Usage: [=13=] [--whatIf]')
        .alias('d', 'directory')
        .alias('wi', 'whatIf')
        .nargs('d', 1)
        .describe('d', 'alphabetize this directory')
        .describe('whatIf', 'show what would happen if run')
        .demandOption(['d'])
        .argv;

console.log(argv.directory);

如果我像这样从 Windows PowerShell 调用脚本:node .\alphabetizer.js -d 'l:\my folder\Files - Some Files In Here\' --whatIf 我得到输出 l:\my folder\Files - Some Files In Here\" --whatIf,而我期望的只是 l:\my folder\Files - Some Files In Here\。它适用于不需要转义的文件夹名称,但它似乎被转义弄糊涂了。

如果我检查 process.argv,我可以看到相同的转义问题。

我注意到,如果我删除结尾的斜杠,它将起作用。然而,这仍然指向节点脚本没有正确处理输入,因为这对于用单引号引起来的字符串来说不是必需的。

有没有办法让它工作?

Windows PowerShell (powershell.exe) 和 PowerShell [Core] v6+ (pwsh) 都在为外部程序引用参数方面从根本上被破坏了 正确 - 请参阅 了解背景信息。

通常,Windows 上的 PowerShell 必须在幕后执行重新引用,以确保 =14=]-quoting 被使用,因为不能假设外部程序在解析它们的命令行时也理解 '...'-quoting(在 Windows 上每个程序都必须自己做)。

Windows PowerShell 更多 损坏 关于 \ 有嵌入空格,不正确地重新引用它们;例如:

PS> foo.exe 'c:\foo \' bar

在后台被翻译成如下命令行:

foo.exe "c:\ foo \" bar

这是 损坏的 ,因为大多数应用程序 - 包括 PowerShell 的 own CLI - 明智地假设 \" 是一个 escaped " 个字符。 逐字,认为论点继续  bar 然后隐式结束,尽管形式上没有结尾 ".

PowerShell [Core] v6+ 更明智地将上面的内容转换为 foo.exe "c:\foo \" bar,其中 \ 被解释为转义的 \,下面的 " 再次具有句法函数。


如果您受困于 Windows PowerShell,您唯一的选择是:

  • 任一:如果可能,去掉尾随 \
  • 否则:手动将其加倍\),但仅当参数还包含空格时才这样做(否则,\ 将按原样保留,但在文件系统路径通常是良性的情况下)。