3

I am trying to use PowerShell to set a condition that if a file name contains any of the following symbols (#, %, &. +. {, }, ~),then replace those symbols with "_". I want to apply this to all file and folder names(including files within sub-folders).

I have below code, which partially works, as it only works for replacing 2 symbols "(%, &)". If i want to replace more symbols it doesn't work. An error message pops up and only the first symbol ends up being replaced. Is there a way to fix this code?

Get-ChildItem -Recurse | `
   Where-Object {$_.Name -match '&' -or $_.Name -match '%' } | `
     Rename-Item -NewName { $_.Name -replace '&','_' -replace '%','_' }

As i have no experience in coding, i would really appreciate if you provide the entire code that would fix this issue, thank you!

Oblivion
  • 7,176
  • 2
  • 14
  • 33
chelseaK
  • 31
  • 1

1 Answers1

4

Use a regex character class/set ([...]) to match all characters of interest:

Get-ChildItem -Recurse | Rename-Item -NewName { $_.Name -replace '[#%&+{}~]', '_' }

Note that I've eliminated the Where-Object call, because it isn't necessary to pre-filter the files:
-replace returns the original string if the regex doesn't match, and Rename-Item is an effective no-op if the -NewName argument is the same as the existing file name.

Also, if you end a line with |, you don't also need ` to signal line continuation.

mklement0
  • 382,024
  • 64
  • 607
  • 775
  • I was trying `get-childitem -filter '*[#%&+{}~]*'` for speed, but it doesn't look like -filter takes the square bracket wildcards. – js2010 Jun 10 '19 at 01:05
  • @js2010: The `-Filter` argument only accepts `?` and `*` - `-Filter` is a _provider_ argument, which in this case is interpreted by the underlying _filesystem_, not by PowerShell - only PowerShell's wildcard language supports `[...]`. – mklement0 Jun 10 '19 at 01:17
  • @mlement0 There's nothing in the documentation that says only a subset of the wildcards work. – js2010 Jun 10 '19 at 01:35
  • @js2010: It's even worse: the documentation actively suggests that PowerShell's wildcard language applies - which is obviously not true, as you've experienced. I encourage you to create a dedicated issue at https://github.com/MicrosoftDocs/PowerShell-Docs/issues. Re what patterns `-Filter` actually supports - see https://stackoverflow.com/a/17739503/45375 – mklement0 Jun 10 '19 at 01:48
  • @js2010: P.S: You could use `-Include` in this case in order to use PowerShell's wildcard language, but that would be slow, because _all_ items must first be retrieved, and _then_ PowerShell's applies filtering. My guess is that you won't gain much in this scenario, and the downside is that you'd have duplicate the search pattern. – mklement0 Jun 10 '19 at 01:50