Please pardon a noob question, but I've been completely baffled by this one.

I have a "depositor" directory where user-submitted files arrive, and have no control over the incoming file names.

I created a parser in PS which quite successfully moves files (based on file name content) to an appropriate destination.

This works fine EXCEPT when a filename contains either "[" or "]".

Here is the "rename" pre-processor, which fails to actually rename a file containing either of the pesky bracket characters:

 cd $folderpath
 foreach ($i in get-childitem $folderpath) {   
     if ($i.mode.substring(0,1) -ne “d”) {
        $name = $i.name.replace("[","_")
        $name = $name.replace("]","_")
        Write-Host $i -foregroundcolor “blue”       
        Write-Host $name -foregroundcolor “green”  

        Rename-Item $i $name 


This also fails for ren, copy, move and their cmdlet equivalents

Any insight you might be able to provide would be most welcome.

Thanks in advance . . .


Unless you use -LiteralPath, square brackets cause real problems with character escaping. The problem comes from PowerShell de-escaping the strings multiple times internally and using special characters for pattern matching. Getting PowerShell to correctly recognize a literal square bracket in a path string is complex.

If you're using single-quote strings, a bracket needs two backticks to escape it. If you're using double-quote strings, a bracket needs four backticks to escape it.

If you're looking for a file named MyFile[1].txt, you need to use either:




Yes, it's a pain. To see why it does this, you have to know what's going on. It's easy to do that by working backwards.

Let's say you want to get a file literally named [ab].txt.

The wildcard pattern matching that Get-ChildItem does means that if it gets [ab].txt as the path, then it will look for files named a.txt and b.txt. So, if we want to match a literal [ab].txt, we have to escape our brackets with the escape character: the backtick. That gives us this as the actual string of characters we want Get-ChildItem to use for the filespec:


However, we have to pass this filespec as a string. That means Get-ChildItem will escape those backticks, but that's not what we want! We want literal backticks. So, we escape the backticks with backticks in our string to make sure Get-ChildItem uses the right filespec:


If we want to use double-quoted strings, then we have to escape each backtick again, as the double-quoted string will de-escape the string. And that's how you end up with this:


This is why so many PowerShell functions that take filespecs have the -LiteralPath option.


RenameItem doesn't have a -LiteralPath for some stupid reason.*

Move-Item -LiteralPath $i -destination $name

* Excuses from a co-designer of the language.

  • Move-Item -LiteralPath $i -destination $name throws this error: Rename-Item : A parameter cannot be found that matches parameter name 'LiteralPath'. – TTrewitt Nov 19 '10 at 22:36
  • @TTrewitt: What version of PS? – Dennis Williamson Nov 19 '10 at 22:41
  • The link in this answer has gone 404. Anyone know of a replacement? – Philip Kendall Jul 18 '13 at 13:01
  • @PhilipKendall: I fixed the link. – Dennis Williamson Jul 18 '13 at 13:07

This finally achieved the desired result:

foreach ($i in get-childitem $folderpath) {
  if ($i.mode.substring(0,1) -ne “d”) {
    $name = $i.name.replace("[","_")
    $name = $name.replace("]","_")

   Write-Host $name -foregroundcolor “green”    
   [System.IO.File]::Move($folderPath+"\"+$i, $folderPath+"\"+$name) 

protected by Dennis Jan 26 '13 at 3:40

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.