I am having difficuty converting a short PowerShell script into a cmd.exe .bat file script. The error message (see below) complains of a `Missing closing '}'. The .ps1 script runs successfully as expected.
I used SEMICOLON characters at the end of assignment statements. I escaped the VERTICAL LINE (pipe) character with a CARET (^). What am I missing?
Here is the .bat script and error message output.
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" ^
"}" ^
"}"
Back in a cmd.exe shell...
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
This is the original .ps1 script which is working as expected.
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".
Running the .ps1 script from a .bat file script also works as expected.
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".
Update:
Taking @mklement0's advice, I have removed QUOTATION MARK characters. The two (2) VERTICAL LINE (pipe) characters are escaped and the beginning-of-line CARET in the -match
regex is escaped. I avoided using QUOTATION MARK characters in the .ps1 script from the beginning. The "Missing closing '}'" failure still occurs. What am I missing?
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
Update 2:
With @mklement0's consistently good advice, here is the working code.
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; ^
}; ^
};