英文:
code --diff fails when filename contains an ampersand '&'
问题
我在尝试使用Visual Studio Code的命令行执行文件差异比对时遇到了一个相当令人困惑的错误。我在云端有一个文本文件,我在其中保存一些与工作相关的笔记。我需要解决与其他客户端编辑该文件的冲突。通常情况下,这只会在连接丢失时发生,但不知何故,我发现自己不得不解决很多这种冲突,所以除了这些冲突以及其他使用差异比对的情况,我会使用通常的语法。它看起来像这样:
code --diff "R&D (cloud conflict 2-5-23).txt" "R&D.txt"
我的文件名中恰好包含'&'字符,这个命令启动了VS Code中的通常的两方差异比对,并能够正常读取第一个文件名,但无法读取第二个'&'字符后的部分,导致在VS Code中的差异标签看起来像这样:
R&D (cloud conflict 2-25-23).txt <-> R
其中右侧的 "R" 不存在。所以似乎'&'需要被按原样处理。
没问题,让我们看看反斜杠''是否可以作为接受的转义参数...
code --diff "R\&D (cloud conflict 2-5-23).txt" "R\&D.txt"
不行。同样的问题。事实上,这输出了一些更奇怪的东西:
Code差异标签:
&D (cloud conflict 2-25-23).txt <-> R
与shell输出:
'D.txt' is not recognized as an internal or external command, operable program or batch file.
我还尝试了'^'符号作为转义参数,有类似的效果。我只在第一个文件名中包含它,但编辑器仍然认为第二个文件名只是 "R"。
VS Code命令行集成的帮助文件对--diff参数除了一个简短的描述外没有提供太多信息,我希望能得到有关如何按原样处理字符串或转义字符的信息。也许还需要其他参数,或者这更多地与一般的shell有关。
我发现它能够读取第一个完整的文件名,但在第二个'&'字符处中断,这真的很奇怪。更奇怪的是,如果在第二个文件名中包含了一个所谓的转义字符,它也会忽略它。
目前,我只能重新命名文件,这真是令人沮丧。我使用的是Windows 10 Home最新版本/构建上的VS Code版本1.75.0,以及PowerShell版本5.1.19041.2364。
编辑:问题明显与PowerShell相关。事实证明,我最终能够在常规命令提示符中成功运行此命令(在运行差异比对命令之前,在PowerShell窗口中输入"cmd"并按Enter)。不幸的是,我恰好是作为PowerShell脚本的一部分来运行这个命令的。如果可能的话,我可能需要弄清楚如何从我的PowerShell脚本中运行CMD命令。我不太确定。如果不行,我需要弄清楚PowerShell到底在处理包含'&'字符的命令时做了什么。
英文:
I am experiencing a rather puzzling error while trying to perform a diff on two files using Visual Studio Code from the command line. I have a text file in the cloud where I save some work related notes. I need to resolve conflicts with other clients editing the file. Usually this only happens during a loss of connection though somehow I find myself having to resolve a lot of them so between this and other uses of diff I will use the usual syntax. It looks something like this:
code --diff "R&D (cloud conflict 2-5-23).txt" "R&D.txt"
My filename happens to have a '&' in it and this command launches the usual 2-way diff in VS Code and reads through the first file name with no problem but doesn't read past the second '&' and the resulting diff tab in VS Code looks something like:
R&D (cloud conflict 2-25-23).txt <-> R
Where the right side "R" doesn't exist. So it would seem '&' needs to be processed literally.
No problem, let's see if backslash \ is an accepted escape parameter...
code --diff "R\&D (cloud conflict 2-5-23).txt" "R\&D.txt"
Nope. Same problem. 🤔 In fact this outputs something even stranger:
Code diff tab:
&D (cloud conflict 2-25-23).txt <-> R
with shell output:
'D.txt' is not recognized as an internal or external command,
operable program or batch file.
I also tried the carrot symbol '^' as an escape parameter to a similar effect. I just includes it in the first file and the editor still thinks the second file name is just "R".
The help file for the VS Code command line integration didn't have a lot to say about the --diff parameter other than a short description and I was hoping to get something about processing strings literally or escape characters. Perhaps another parameter that I need or maybe this has more to do with the shell in general.
I find it really strange that it can read the first full file name but breaks at the second '&'. Weirder still that if a supposed escape character is included in the second file name, it will omit that as well. 😵
For now all I can do is rename the file which is a bummer. 🤷♂️ I have VS Code version 1.75.0 on Windows 10 Home latest version/build and I'm using PowerShell version 5.1.19041.2364.
Edit: The issue definitely appears to be PowerShell related as it turns out. I was finally able to run this command successfully in a regular command prompt. (Simply typing "cmd" and Enter into the PowerShell window before running the diff command). Unfortunately, I happen to be running this command as part of PowerShell script. I may have to figure out how to run a CMD command from inside my PowerShell script if that is at all possible. I'm not sure. 🤔 If not, I need to figure out what exactly PowerShell is doing to my command when it reaches the '&' character.
答案1
得分: 1
以下是翻译好的部分:
tl;dr
您需要一个解决方法:
cmd /c 'code --diff "R&D (cloud conflict 2-5-23).txt" "R&D.txt"'
或者,使用--%
,停止解析标记:
code --diff "R&D (cloud conflict 2-5-23).txt" --% "R&D.txt"
- 注意:
--%
存在根本限制,特别是无法引用PowerShell变量 - 请参考此答案。
背景信息:
-
根本原因是
code
被实现为批处理文件(code.cmd
),而cmd.exe
,执行批处理文件的解释器,不当地解析其参数列表,就好像它们是从cmd.exe
会话内部提交的一样。 -
PowerShell必须在Windows上在执行参数解析后在幕后重新构建进程命令行,根据其规则进行参数解析,因此,将
"R&D.txt"
视为命令行上的R&D.txt
,因为参数值不包含空格是合理的。 -
结果是,
cmd.exe
解释其命令行上未加引号的R&D.txt
参数,其中包含元字符&
,这是其命令序列运算符,导致调用中断。 -
鉴于
cmd.exe
,即传统的Windows shell,不太可能获得修复,积极维护的PowerShell(Core)7+版本可以作为一种礼貌方式来补偿cmd.exe
不当的行为。- 这已经在GitHub问题#15143中提出,但遗憾的是,似乎不会实施这些调整。
英文:
<!-- language-all: sh -->
tl;dr
You need a workaround:
cmd /c 'code --diff "R&D (cloud conflict 2-5-23).txt" "R&D.txt"'
Alternatively, using --%
, the stop-parsing token:
code --diff "R&D (cloud conflict 2-5-23).txt" --% "R&D.txt"
- Note:
--%
comes with fundamental limitations, notably the inability to reference PowerShell variables - see this answer.
Background information:
-
The root cause is that
code
is implemented as a batch file (code.cmd
) and thatcmd.exe
, the interpreter that executes batch file inappropriately parses its list of arguments as if they had been submitted from INSIDE acmd.exe
session. -
PowerShell, which - of necessity - has to rebuild the process command line behind the scenes on Windows after having performed argument parsing based on its rules, and - justifiably - places
"R&D.txt"
as verbatimR&D.txt
on the process command line, given that the argument value contains no spaces. -
The result is that
cmd.exe
interprets the unquotedR&D.txt
argument on its command line as containing metacharacter&
, which is its command-sequencing operator, causing the call to break. -
Given that
cmd.exe
, the legacy Windows shell, is unlikely to receive fixes, the actively maintained PowerShell (Core) 7+ edition could as a courtesy compensate forcmd.exe
's inappropriate behavior.- Doing so has been proposed in GitHub issue #15143, but, alas, it looks like these accommodations will not be implemented.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论