Remove characters from file names with PowerShell

As we all know, OneDrive does not accept files or folders containing certain characters, so here is a short guide on how to remove characters from file names with PowerShell.

To start, here is a list of all the characters that aren’t supported, some of these might be more commonly used than others, but I’ve seen a lot of “creative” users. (Some of these aren’t possible to use in file names or folder names)

\
/
:
,
?
&
#
{
}
#
{
}
<
>
%
~
<
>
|

The first thing we need to do, is to select a folder that we should search and find all files and folders in it. I prefer to set this as a variable since I often need to use the path again later on in the script. To do this, use the following code:

$Folder = "C:\Demo\"
$Items = Get-ChildItem -Path $Folder -Recurse

Now that we have all our files and folders stored in “$Items”, we need to create a variable that contains all the unsupported characters. (I will only use the ones that can be used on the file system, but not on SharePoint/OneDrive)

This is the content of my “Demo folder”

Before

Before

$UnsupportedChars = '[!$&{}~#%]'

Next step is to create a loop that will cycle through all the files and folders in “$Items” and match them with the characters in “$UnsupportedChars”, then create a new file name that we will use instead. (Either removes the character or replaces it with something else)

In the example below, I will replace the “&” with “and” and other characters will be removed.

foreach ($item in $items){
 filter Matches($UnsupportedChars){
 $item.Name | Select-String -AllMatches $UnsupportedChars |
 Select-Object -ExpandProperty Matches
 Select-Object -ExpandProperty Values
 }

 $newFileName = $item.Name
 Matches $UnsupportedChars | ForEach-Object {
 Write-Host "$($item.FullName) has the illegal character $($_.Value)" -ForegroundColor Red
 if ($_.Value -match "&") { $newFileName = ($newFileName -replace "&", "and") }
 if ($_.Value -match "{") { $newFileName = ($newFileName -replace "{", "(") }
 if ($_.Value -match "}") { $newFileName = ($newFileName -replace "}", ")") }
 if ($_.Value -match "~") { $newFileName = ($newFileName -replace "~", "-") }
 if ($_.Value -match "#") { $newFileName = ($newFileName -replace "#", "") }
 if ($_.Value -match "%") { $newFileName = ($newFileName -replace "%", "") }
 if ($_.Value -match "!") { $newFileName = ($newFileName -replace "!", "") }
 }
}

If we run the complete code in PowerShell, the items will be printed in red in the console. This is a good start, we can now see how many items there are that won’t be synced with OneDrive, but this doesn’t rename the files automatically. To do this, we need to add the following to the loop:

if ($newFileName -ne $item.Name){
        Rename-Item $item.FullName -NewName ($newFileName)
        Write-Host "$item.Name has been changed to $newFileName" -ForegroundColor Green
}

This, with the part before, will check if the file name is the same after we have run the first part. If it’s not, it will rename the file or folder to the new name.
It will also write the new name of the file or folder in green in the console.

So, the complete code should look like this:

$Folder = "C:\Demo\"
$Items = Get-ChildItem -Path $Folder -Recurse

$UnsupportedChars = '[!&{}~#%]'

foreach ($item in $items){
    filter Matches($UnsupportedChars){
    $item.Name | Select-String -AllMatches $UnsupportedChars |
    Select-Object -ExpandProperty Matches
    Select-Object -ExpandProperty Values
    }

    $newFileName = $item.Name
    Matches $UnsupportedChars | ForEach-Object {
        Write-Host "$($item.FullName) has the illegal character $($_.Value)" -ForegroundColor Red
        #These characters may be used on the file system but not SharePoint
        if ($_.Value -match "&") { $newFileName = ($newFileName -replace "&", "and") }
        if ($_.Value -match "{") { $newFileName = ($newFileName -replace "{", "(") }
        if ($_.Value -match "}") { $newFileName = ($newFileName -replace "}", ")") }
        if ($_.Value -match "~") { $newFileName = ($newFileName -replace "~", "-") }
        if ($_.Value -match "#") { $newFileName = ($newFileName -replace "#", "") }
        if ($_.Value -match "%") { $newFileName = ($newFileName -replace "%", "") }
        if ($_.Value -match "!") { $newFileName = ($newFileName -replace "!", "") }
     }
     if (($newFileName -ne $item.Name)){
        Rename-Item $item.FullName -NewName ($newFileName)
        Write-Host "$($item.Name) has been changed to $newFileName" -ForegroundColor Green
     }
}

After the script has been run, the folder looks like this and the output in the console is shown just below.

After

After

Output

Output

Just remember to change the “$Folder” to suit your needs.

This script has been uploaded to the gallery at Technet as well. Fully functional function that can easily be used: https://gallery.technet.microsoft.com/Check-for-unsupported-6676929a

For more guides and scripts, follow this LINK

This entry was posted in Powershell and tagged , , , , , , . Bookmark the permalink.

4 Responses to Remove characters from file names with PowerShell

  1. Pingback: PowerShell Guides - A guide to Microsoft ProductsA guide to Microsoft Products

  2. howard brooks says:

    The Long path tool is the very best program for error, unlock solution.and it is very useful tool.

  3. John says:

    This is a great example but when the , and $ are added to the $UnsupportedChars list the PowerShell script does not work. I also notice that it is not fixing files in the subfolders. The Function information has been taken out so it runs as a pure PowerShell script (the removal $Fix parameter is gone as well).

    What might be the problem?

    • admin says:

      Hi!

      If you aren’t using the function, make sure that you have the “-Recurse” switch added to your “Get-ChildItem”. (Easily missed)
      For the $ character I don’t have an answer at the moment, let me check the script and get back to you!

      //Andreas

Leave a Reply

Your email address will not be published. Required fields are marked *