带双引号的批处理文件多行命令

Maz*_*aka 7 windows cmd batch-file

使用^符号输入带有参数的多行命令时使用双引号来使用带空格的字符串^符号也会被传递,有人可以解释这是什么方式吗?

working.cmd

@echo off 
call openfiles.cmd ^
C:\dir\filename.txt ^
C:\another_dir\another_file.txt
Run Code Online (Sandbox Code Playgroud)

notworking.cmd

@echo off 
call openfiles.cmd ^
"C:\dir with spaces\file with spaces.txt" ^
"C:\another dir with spaces\another file with spaces.txt"
Run Code Online (Sandbox Code Playgroud)

openfiles.cmd看起来像

@echo off
for %%x in (%*) do (

    IF EXIST %%x (
        call "c:\Program Files\Notepad++\notepad++.exe" %%x
    ) ELSE (
        call echo Not found %%x
    )

)

pause
Run Code Online (Sandbox Code Playgroud)

我得到的错误

C:\>call openfiles.cmd "C:\dir with spaces\file with spaces.txt" ^
ELSE was unexpected at this time.
Run Code Online (Sandbox Code Playgroud)

jeb*_*jeb 7

问题是,第二行开头的引号将被多行插入符号转义.
因此,行中的最后一个引号开始引用而不是停止引用,因此第二行中的插入符号作为普通字符处理.

call openfiles.cmd ^"C:\dir with spaces\file with spaces.txt" ^
**This is a seperate line** "C:\another dir with spaces\another file with spaces.txt"
Run Code Online (Sandbox Code Playgroud)

插入符号规则:

插入符号逃脱了下一个角色,因此角色会失去所有特效.
如果下一个字符是换行符,则删除此字符并取下一个字符(即使这也是换行符).

通过这个简单的规则,你可以解释像

echo #1 Cat^&Dog
echo #2 Cat^
&Dog
echo #3 Redirect to > Cat^
 Dog

setlocal EnableDelayedExpansion
set linefeed=^


echo #4 line1!linefeed!line2
Run Code Online (Sandbox Code Playgroud)

#3 创建一个名为"Cat Dog"的文件,因为空间已被转义,并且不再作为分隔符.

但它仍有可能打破这个规则!
你只需要在插入符号前面放置任何重定向,它仍然会丢弃换行符(多行仍然有效),但下一个字符不再被转义.

echo #5 Line1< nul ^
& echo Line2
Run Code Online (Sandbox Code Playgroud)

所以你也可以使用它来构建你的多线命令

call openfiles.cmd < nul ^
"C:\dir with spaces\file with spaces.txt" < nul ^
"C:\another dir with spaces\another file with spaces.txt"
Run Code Online (Sandbox Code Playgroud)

或者使用

set "\n=< nul ^"
call openfiles.cmd %\n%
"C:\dir with spaces\file with spaces.txt" %\n%
"C:\another dir with spaces\another file with spaces.txt"
Run Code Online (Sandbox Code Playgroud)


Pau*_*rez 5

简而言之:

"字符需要^转义,否则 cmd 会逐字复制出现在对之间的^字符。"

警告^按字面意思复制插入符号后面的字符,使其失去任何元字符功能(如果有)。在多行场景中,不仅换行符/换行符会被逐字复制,而且新行中的第一个字符也会被转义

解释:

插入符号^ 字符

以下定义摘自Daniel Colascione于 2011 年 4 月 23 日发表的文章“每个人都以错误的方式引用命令行参数”的一个小节

更好的引用方法

虽然"元字符不能完全保护命令行中的元字符免受意外的 shell 解释,但^ 元字符可以。当 cmd 转换命令行并看到 a 时^,它会忽略 ^ 字符本身,并将下一个字符逐字复制到新命令行,无论是否是元字符。 这就是为什么^用作行继续字符:它告诉 cmd 将后续换行符复制为自身,而不是将该换行符视为命令终止符。如果我们^在参数字符串中添加每个元字符作为前缀,cmd 就会将该字符串转换为我们想要使用的字符串。

现在是与所提出的问题相关的重要部分:

对字符进行转义^"很重要:否则,cmd 会逐字复制^出现在对之间的字符",从而破坏该过程中的参数字符串。

请注意,当您 时^", 会"失去其引用功能,因此必须小心。


演示:

没有^-转义"

"c:\Program^
 Files\test.bat"
Run Code Online (Sandbox Code Playgroud)

变成

"c:\Program^
Files\test.bat"
Run Code Online (Sandbox Code Playgroud)

^-转义"

^"c:\Program^
 Files\test.bat^"
Run Code Online (Sandbox Code Playgroud)

变成

"c:\Program Files\test.bat"
Run Code Online (Sandbox Code Playgroud)

并执行程序

请注意,^对引号进行 - 转义会使它们失去引用功能,因此该命令也可以执行为:c:\Program^ Files\test.bat。我们通常将其放在引号中的原因是为了删除空格元字符的分隔功能,但是转义空格字符的插入符提供了相同的功能。

使用^-escaping ",但空格移至上一行

^"c:\Program ^
Files\test.bat^"
Run Code Online (Sandbox Code Playgroud)

变成

"c:\Program Files\test.bat"
Run Code Online (Sandbox Code Playgroud)

但命令行报告“c:\Program”无法识别...

这是因为第一行的空格字符和转义"字符将被解释为分隔符而不是字符。^<space>

在第二个示例中, the<space>是换行符中 a 之后的第一个字符^,因此被转义并解释为字符而不是分隔符。


来源: 微软博客文章