0

I'm having trouble passing file names from batch to a powershell command. I need to change the encoding of all files in a subdirectory of the current directory. Some filenames contain apostrophes, and I would rather leave those intact.

Here is my first go at the code:

for /R "%cd%\Legacy .xml files\" %%f in (*.xml) do (
    echo. file: %%~nxf
    set filename=%%~nxf
    powershell -Command "& {Get-Content '%%f' | Set-Content -Encoding utf8 '%cd%\XML converted to UTF-8\!filename!';}"
)

That gave this error for files with apostrophes in the name, e.g. D'Este.xml (note - there are several files with apostrophes):

Get-Content : A positional parameter cannot be found that accepts argument 'Este.xml | Set-Content -Encoding utf8
C:\Users\pwessels\Documents\Report'.
At line:1 char:4
+ & {Get-Content 'C:\Users\pwessels\Documents\Report tinkering\Ops-Dail ...
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [Get-Content], ParameterBindingException
    + FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.GetContentCommand

Then I tried escaped double quotes instead of single quotes in the powershell command, but I receive a different error (on every file this time).

for /R "%cd%\Legacy .xml files\" %%f in (*.xml) do (
    echo. file: %%~nxf
    set filename=%%~nxf
    powershell -Command "& {Get-Content ""%%f"" | Set-Content -Encoding utf8 ""%cd%\XML converted to UTF-8\!filename!"";}"
)

That gave this error:

The string is missing the terminator: ".
    + CategoryInfo          : ParserError: (:) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : TerminatorExpectedAtEndOfString

Looking for any insight on how to accomplish this!

EDIT: Powershell attempt doesn't work either - I'm not experienced at all with powershell and I'm getting a Set-ExecutionPolicy error that I couldn't find the solution for.

Get-ChildItem "$PSScriptRoot\Legacy .xml files" -Filter *.xml | 
Foreach-Object {
    $content = Get-Content $_.FullName

    #filter and save content to the original file
    $content | Set-Content -Encoding utf8 "$($PSScriptRoot)\XML converted to UTF-8\$($_.ShortName).xml"
}
Read-Host -Prompt "Press Enter to exit"

error:

Set-ExecutionPolicy : Windows PowerShell updated your execution policy successfully, but the setting is overridden by
a policy defined at a more specific scope.  Due to the override, your shell will retain its current effective
execution policy of RemoteSigned. Type "Get-ExecutionPolicy -List" to view your execution policy settings. For more
information please see "Get-Help Set-ExecutionPolicy".
At line:1 char:46
+ ...  -ne 'AllSigned') { Set-ExecutionPolicy -Scope Process Bypass }; & 'C ...
+                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : PermissionDenied: (:) [Set-ExecutionPolicy], SecurityException
    + FullyQualifiedErrorId : ExecutionPolicyOverride,Microsoft.PowerShell.Commands.SetExecutionPolicyCommand
  • Perhaps these help: [How to get around using apostrophe in double quotes with Powershell](https://stackoverflow.com/q/60643956) or [Escape apostrophes from variable in powershell](https://stackoverflow.com/q/44488383) – aschipfl Mar 19 '21 at 18:46
  • @aschipfl Just tried adding `set filename=!filename:'=``'!` and unfortunately it didn't work. – Phillip Wessels Mar 19 '21 at 19:00
  • 3
    everything you show in that BAT script can be done entirely in PoSh. so ... why not do it all in powershell? – Lee_Dailey Mar 19 '21 at 20:55
  • @Lee_Dailey There's more in the batch file than this - also I'm more comfortable with batch files than powershell scripts, so they're what I go for. – Phillip Wessels Mar 19 '21 at 21:58
  • @Lee_Dailey I did try powershell but I'm not sure what I'm getting wrong (edited post to contain powershell attempt) – Phillip Wessels Mar 19 '21 at 21:59
  • 1
    [1] you should not need to set the execution policy. [2] setting that inside your script will not change it for that script - it will only apply to later sessions. [3] your error text shows code that is not in your posted PoSh script ... so where is that code coming from? – Lee_Dailey Mar 19 '21 at 22:14
  • @Lee_Dailey There's nothing about execution policy in my script so I have no idea the posted code is everything in this .ps1 file – Phillip Wessels Mar 19 '21 at 23:16
  • @PhillipWessels - if you load another PoSh script & run it ... do you see that error? does it only happen in one PoSh host? only the ISE, or the powershell.exe, or pwsh.exe ... i can't think of any other source than the profile for something so odd. – Lee_Dailey Mar 20 '21 at 01:13
  • In a batch file: use inner double quotes _quadrupled_ as follows (truncated): `powershell -Command "& {Get-Content """"%%~f""""}"` – JosefZ Mar 20 '21 at 16:32

1 Answers1

0

I had the same problem in a DOS script that I wrote. My solution is in the following code fragment. It is from a DOS script that calls a PowerShell script, Remove-ItemSafely to "delete" tmp files by moving them to the recycle bin. If any filename in the current directory an an apostrophe, it is replaced with two apostrophes in a temporary variable before the PowerShell command is called.

setlocal EnableDelayedExpansion
for /r %%f in (*.tmp) do (
   
    echo.
    echo original filename %%f
    set "c_tmp=%%f" & set "c_tmp=!c_tmp:'=''!"

    echo modified filename !c_tmp!
    echo powershell.exe -command "& Remove-ItemSafely '!c_tmp!'"
         powershell.exe -command "& Remove-ItemSafely '!c_tmp!'"
)

Of course you can adapt the code according to your needs. Just use !c_tmp! as the modified filename.

Paul Roub
  • 36,322
  • 27
  • 84
  • 93