powershell - .ps1 脚本在 .bat 文件脚本中报告为“缺少关闭 '}'”
问题描述
我很难将简短的 PowerShell 脚本转换为 cmd.exe .bat 文件脚本。错误消息(见下文)抱怨“缺少关闭 '}”。.ps1 脚本按预期成功运行。
我在赋值语句的末尾使用了分号字符。我用 CARET (^) 转义了 VERTICAL LINE(竖线)字符。我错过了什么?
这是 .bat 脚本和错误消息输出。
PS C:\src\t> Get-Content -Path .\DistributeFiles2.bat
powershell -NoLogo -NoProfile -Command ^
"$ProjectPath = Join-Path -Path $Env:USERPROFILE -ChildPath 'Desktop\Project';" ^
"$NFilesPerDirectory = 400;" ^
"Get-ChildItem -File -Path (Join-Path -Path $Env:USERPROFILE -ChildPath 'Desktop\images') -Filter '*.jpeg' ^|" ^
"ForEach-Object {" ^
"# Check to see if the filename starts with four (4) digits.;" ^
"if ($_.BaseName -match '^(\d{4}).*') {" ^
"$FolderNumber = [math]::Floor([int]$Matches[1] / $NFilesPerDirectory);" ^
"$FolderName = 'Folder' + $FolderNumber.ToString();" ^
"$FolderPath = Join-Path -Path $ProjectPath -ChildPath $FolderName;" ^
"# If the destination directory does not exist, create it.;" ^
"if (-not (Test-Path -Path $FolderPath)) { mkdir $FolderPath -WhatIf ^| Out-Null }" ^
"# Move the file to the destination directory.;" ^
"Move-Item -Path $_.FullName -Destination $FolderPath -WhatIf" ^
"}" ^
"}"
回到 cmd.exe 外壳...
C:>DistributeFiles2.bat
9:55:41.67 C:\src\t
C:>powershell -NoLogo -NoProfile -Command "$ProjectPath = Join-Path -Path $Env:USERPROFILE -ChildPath 'Desktop\Project';" "$NFilesPerDirectory = 400;" "Get-ChildItem -File -Path (Join-Path -Path $Env:USERPROFILE -ChildPath 'Desktop\images') -Filter '*.jpeg' ^|" "ForEach-Object {" "# Check to see if the filename starts with four (4) digits.;" "if ($_.BaseName -match '^(\d{4}).*') {" "$FolderNumber = [math]::Floor([int]$Matches[1] / $NFilesPerDirectory);" "$FolderName = 'Folder' + $FolderNumber.ToString();" "$FolderPath = Join-Path -Path $ProjectPath -ChildPath $FolderName;" "# If the destination directory does not exist, create it.;" "if (-not (Test-Path -Path $FolderPath)) { mkdir $FolderPath -WhatIf ^| Out-Null }" "# Move the file to the destination directory.;" "Move-Item -Path $_.FullName -Destination $FolderPath -WhatIf" "}" "}"
Missing closing '}' in statement block or type definition.
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : MissingEndCurlyBrace
这是按预期工作的原始 .ps1 脚本。
PS C:\src\t> Get-Content -Path .\DistributeFiles.ps1
$ProjectPath = Join-Path -Path $Env:USERPROFILE -ChildPath 'Desktop\Project';
$NFilesPerDirectory = 400;
Get-ChildItem -File -Path (Join-Path -Path $Env:USERPROFILE -ChildPath 'Desktop\images') -Filter '*.jpeg' |
ForEach-Object {
# Check to see if the filename starts with four (4) digits.;
if ($_.BaseName -match '^(\d{4}).*') {
$FolderNumber = [math]::Floor([int]$Matches[1] / $NFilesPerDirectory);
$FolderName = 'Folder' + $FolderNumber.ToString();
$FolderPath = Join-Path -Path $ProjectPath -ChildPath $FolderName;
# If the destination directory does not exist, create it.;
if (-not (Test-Path -Path $FolderPath)) { mkdir $FolderPath -WhatIf | Out-Null }
# Move the file to the destination directory.;
Move-Item -Path $_.FullName -Destination $FolderPath -WhatIf
}
}
PS C:\src\t> .\DistributeFiles.ps1
What if: Performing the operation "Create Directory" on target "Destination: C:\Users\lit\Desktop\Project\Folder0".
What if: Performing the operation "Move File" on target "Item: C:\Users\lit\Desktop\images\0000.jpeg Destination: C:\Users\lit\Desktop\Project\Folder0".
What if: Performing the operation "Create Directory" on target "Destination: C:\Users\lit\Desktop\Project\Folder1".
What if: Performing the operation "Move File" on target "Item: C:\Users\lit\Desktop\images\0401.jpeg Destination: C:\Users\lit\Desktop\Project\Folder1".
从 .bat 文件脚本运行 .ps1 脚本也可以按预期工作。
PS C:\src\t> Get-Content -Path .\DistributeFiles.bat
@powershell -NoLogo -NoProfile -File "%~dp0%~n0.ps1"
PS C:\src\t> .\DistributeFiles.bat
What if: Performing the operation "Create Directory" on target "Destination: C:\Users\lit\Desktop\Project\Folder0".
What if: Performing the operation "Move File" on target "Item: C:\Users\lit\Desktop\images\0000.jpeg Destination: C:\Users\lit\Desktop\Project\Folder0".
What if: Performing the operation "Create Directory" on target "Destination: C:\Users\lit\Desktop\Project\Folder1".
What if: Performing the operation "Move File" on target "Item: C:\Users\lit\Desktop\images\0401.jpeg Destination: C:\Users\lit\Desktop\Project\Folder1".
更新:
接受@mklement0 的建议,我删除了引号字符。两 (2) 个 VERTICAL LINE(竖线)字符被转义,正则表达式中的行首 CARET-match
被转义。我从一开始就避免在 .ps1 脚本中使用引号字符。“缺少关闭'}'”失败仍然发生。我错过了什么?
C:>powershell -NoLogo -NoProfile -Command ^
More? $ProjectPath = Join-Path -Path $Env:USERPROFILE -ChildPath 'Desktop\Project'; ^
More? $NFilesPerDirectory = 400; ^
More? Get-ChildItem -File -Path (Join-Path -Path $Env:USERPROFILE -ChildPath 'Desktop\images') -Filter '*.jpeg' ^| ^
More? ForEach-Object { ^
More? # Check to see if the filename starts with four (4) digits.; ^
More? if ($_.BaseName -match '^^(\d{4}).*') { ^
More? $FolderNumber = [math]::Floor([int]$Matches[1] / $NFilesPerDirectory); ^
More? $FolderName = 'Folder' + $FolderNumber.ToString(); ^
More? $FolderPath = Join-Path -Path $ProjectPath -ChildPath $FolderName; ^
More? # If the destination directory does not exist, create it.; ^
More? if (-not (Test-Path -Path $FolderPath)) { mkdir $FolderPath -WhatIf ^| Out-Null }; ^
More? # Move the file to the destination directory.; ^
More? Move-Item -Path $_.FullName -Destination $FolderPath -WhatIf; ^
More? }; ^
More? };
Missing closing '}' in statement block or type definition.
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : MissingEndCurlyBrace
更新 2:
有了@mklement0 一贯的好建议,这里是工作代码。
powershell -NoLogo -NoProfile -Command ^
$ProjectPath = Join-Path -Path $Env:USERPROFILE -ChildPath 'Desktop\Project'; ^
$NFilesPerDirectory = 400; ^
Get-ChildItem -File -Path (Join-Path -Path $Env:USERPROFILE -ChildPath 'Desktop\images') -Filter '*.jpeg' ^| ^
ForEach-Object { ^
^<# Check to see if the filename starts with four (4) digits.#^> ^
if ($_.BaseName -match '^^(\d{4}).*') { ^
$FolderNumber = [math]::Floor([int]$Matches[1] / $NFilesPerDirectory); ^
$FolderName = 'Folder' + $FolderNumber.ToString(); ^
$FolderPath = Join-Path -Path $ProjectPath -ChildPath $FolderName; ^
^<# If the destination directory does not exist, create it.#^> ^
if (-not (Test-Path -Path $FolderPath)) { mkdir $FolderPath -WhatIf ^| Out-Null }; ^
^<# Move the file to the destination directory.#^> ^
Move-Item -Path $_.FullName -Destination $FolderPath -WhatIf; ^
}; ^
};
解决方案
在
cmd.exe
批处理文件中,因此也在批处理文件中,^
仅充当未引用字符串中的转义字符;因此,一般情况下,您不需要转义cmd.exe
元字符,例如字符串|
内部,因为- 如果您这样做,这些字符将被保留。"..."
^|
^
但是,看起来使用带有双引号的每行字符串
cmd.exe
的行继续(行结尾^
)不能正常工作(并且从根本上不支持单个双引号字符串跨越多行),所以解决方案是使用不带引号的行,您确实需要在其上转义|
为^|
,以及其他字符。
下面是一个练习各种 PowerShell 语法结构的示例:
powershell -NoProfile -Command ^
[Environment]::CommandLine; ^
$ProjectPath = Join-Path -Path $Env:USERPROFILE -ChildPath 'Desktop\Project'; ^
^<# This is a comment - note the required *inline* comment syntax #^> ^
$ProjectPath ^| ^
ForEach-Object { \"[$ProjectPath]\" }; ^
(42).ToString(); ^
\"A & B\"
请注意[Environment]::CommandLine;
作为第一条语句的包含,它将回显 PowerShell 所看到的命令行,这可以帮助进行故障排除。顺便说一句:当使用 PowerShell (Core) 7+ 的 CLI,pwsh.exe
而不是 Windows PowerShell 的powershell.exe
时,报告的命令行是一种重构形式,不能保证反映实际使用的命令行;值得注意的是,""
序列转向\"
.
笔记:
每个内部行必须具有
^
作为该行的最后一个字符。因为续行不包括换行符,所以
;
必须用于显式终止每个 PowerShell 语句(最后一个除外)。注意:在语句之间插入空行(不以 结尾)不起作用:虽然它在传递给 PowerShell 时在技术上确实会产生一个实际的换行符,但缺少整体双引号使得 PowerShell 将此类换行符视为与空格相同,这因此仍然需要在语句之间。
^
;
正是由于这个原因,此调用方法不支持单行注释 (
# ...
) ,因为此类注释总是跨越行的其余部分,不支持结束它们 - 请参阅下一点。;
为了包含注释,必须使用表单
^<# ... #^>
- 即(转义的)内联注释 -不支持普通的单行注释 (# ....
) (参见前一点)。cmd.exe
的元字符需要单独的^
-escaping,即:& | < > ^
- 此外,如果从
for /f
语句调用:= , ; ( )
"
字符必须进行转义,\"
以便PowerShell将它们视为要执行的命令的一部分(否则它们会在命令行解析期间被剥离)。在内部
\"...\"
,cmd.exe
元字符不需要-escaping^
,因为cmd.exe
将这样的 PowerShell 转义字符串视为常规双引号字符串。但是,空白归一化应用于内部
\"...\"
;即,多个空间的运行被每个折叠成一个空间;如果这是一个问题,请使用^"\"...\"^"
(原文如此)。
有关其他信息,包括
for /f
示例以及如何处理转义!
何时setlocal enabledelayedexpansion
生效,请参阅此答案。
推荐阅读
- imagemagick - ImageMagick convert 没有创建动画 gif
- javascript - 在 Mongodb 中使用 Ajax
- r - R:如何为多项式 logit 格式化我的数据?
- ssh - 我可以通过命令行 SSH 到本地 Weblogic AdminServer 吗?
- android - 带有导航组件的幻灯片动画
- javascript - Lodash - 将对象移动到数组中的第一位而不是按另一个属性排序
- azure - 如何在 azure devops 中构建和部署 dacpac
- python - 为什么 correlate2d 返回噪声?
- r - 使用 plotFun 在 R 中绘制两个变量的函数
- mysql - 从工作台向 MySQL 8.0 中插入一个点