TransWikia.com

Escaping parenthesis in PowerShell Invoke-Expression

Super User Asked on December 5, 2021

Below is a one-line script I am writing that is causing problems when I try to add an open-paran within invoke-expression.

Within the script, the file map.txt contains 800 lines of 3 digit numbers. The script is intended to change the name of existing files that start with 001..400 (unique/non-repeating) by prefixing a new (unique) three digit number and space before the existing file. To do this, the a three-digit number is extracted from map.txt to find the file I want renamed (using invoke-expression "ls $line1 (*" and the next line in map.txt is the number that should be prefixed to the existing file. So, if the first two lines of map.txt are 001 and 008, the file, 001 (additional characters).ext (parentheses are part of file name) will be changed to 008 001 (additional characters).ext

It will execute if I remove the open-paran within invoke-expression. However, without the open-paran within invoke-expression, when the map.txt file comes to a number pair of 008 021, it will try to rename the 008 001 (additional characters).ext that has already been renamed. Adding the open-paren makes files names unique regardless of name changes that have already occurred and the script should execute as desired. That is, if I can figure out how to include an open-paren within invoke expression. I could probably do a work around with a few lines of regex and -match but if I can find a quick solution to include the open-paran with invoke-expression, it would be ideal.

Thanks for your help.

for ($i=0; $i -lt 800; $i=($i+"2")) {$line1=(get-content ..map.txt | select -index $i); $line2=(get-content ..map.txt | select -index ($i+"1")); $old=(invoke-expression 'ls $line1 (*'); $fileold=($old.basename+$old.extension); $filenew=($line2+" "+$fileold); mv "$fileold" "$filenew"} 

One Answer

To make Invoke-Expression 'ls $line1 (*' or Invoke-Expression "ls $line1 (*" work as intended, quote the line you want to pass to ls with different quotes, like Invoke-Expression 'ls "$line1 (*"' or Invoke-Expression "ls '$line1 (*'".


Furthermore, I would like to recommend the following code optimization to you:

$numbers = Get-Content -Path "..map.txt"
for ($i = 0; $i -lt 400; $i++) {
    Get-Item -Path "$($numbers[2*$i]) (*" | ForEach-Object -Process {Rename-Item -Path $_.Name -NewName "$($numbers[2*$i+1]) $($_.Name)"}
}

And if you want to squeeze that into one line, you can do it like this:

$n=gc ..map.txt;for($i=0;$i-lt400;$i++){gi "$($n[2*$i]) (*"|%{rni $_ "$($n[2*$i+1]) $($_.Name)"}}

Answered by stackprotector on December 5, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP