I'm trying to rename file based on pattern and then move them to a new folder
$ltmpPath = "D:somepath\Temp\"
$ldstPath = "D:\OtherPath\Folder\"
get-childItem $ltmpPath | rename-item -newname { $_.name -replace "(^[a-z]+)(\d\d\d\d)\.pdf", "sg`${2}14.pdf"
get-childItem $ltmpPath | Where-Object { $_.name -match "(^sg)(\d\d\d\d\d\d)\.pdf"} | move-item -Destination $ldstPath -WhatIf
All it does is copying every file to a file D:\OtherPath\Folder instead of D:\OtherPath\Folder\sgxxxxxx.pdf.
What if: Performing the operation "Move File" on target "Item: D:somepath\Temp\sg311014.pdf Destination: D:\OtherPath\Folder\".
Related
I wrote the script below to batch rename files with powershell. It is intended to remove dots (.) and every (-) that is followed by a number from the filenames. Example: text.10-1 becomes text101. However, I feel like there must be a way to do this in a line of code.
Also, I wanted it to also enter a subdirectory and do it, how do I write it?
Get-ChildItem | ForEach{ $_ | Rename-Item -NewName "$($_.BaseName.Replace(".",'')+$_.Extension)" }
Get-ChildItem | ForEach{ $_ | Rename-Item -NewName "$($_.BaseName.Replace("-1",'1')+$_.Extension)" }
Get-ChildItem | ForEach{ $_ | Rename-Item -NewName "$($_.BaseName.Replace("-0",'0')+$_.Extension)" }
Get-ChildItem | ForEach{ $_ | Rename-Item -NewName "$($_.BaseName.Replace("-2",'2')+$_.Extension)" }
Get-ChildItem | ForEach{ $_ | Rename-Item -NewName "$($_.BaseName.Replace("-3",'3')+$_.Extension)" }
Get-ChildItem | ForEach{ $_ | Rename-Item -NewName "$($_.BaseName.Replace("-4",'4')+$_.Extension)" }
Get-ChildItem | ForEach{ $_ | Rename-Item -NewName "$($_.BaseName.Replace("-5",'5')+$_.Extension)" }
Get-ChildItem | ForEach{ $_ | Rename-Item -NewName "$($_.BaseName.Replace("-6",'6')+$_.Extension)" }
Get-ChildItem | ForEach{ $_ | Rename-Item -NewName "$($_.BaseName.Replace("-7",'7')+$_.Extension)" }
Get-ChildItem | ForEach{ $_ | Rename-Item -NewName "$($_.BaseName.Replace("-8",'8')+$_.Extension)" }
Get-ChildItem | ForEach{ $_ | Rename-Item -NewName "$($_.BaseName.Replace("-9",'9')+$_.Extension)" }
Thanks
How about this? Get-childitem in parens to avoid the "modifying the loop" problem.
echo hi | set-content -1.txt,-2.txt,-3.txt
(get-childitem) | rename-item -newname { $_.name -replace '-(\d)','$1' } -whatif
What if: Performing the operation "Rename File" on target "Item: C:\users\admin\foo\-1.txt Destination: C:\users\admin\foo\1.txt".
What if: Performing the operation "Rename File" on target "Item: C:\users\admin\foo\-2.txt Destination: C:\users\admin\foo\2.txt".
What if: Performing the operation "Rename File" on target "Item: C:\users\admin\foo\-3.txt Destination: C:\users\admin\foo\3.txt".
You can do this with a single Get-ChildItem call:
(Get-ChildItem -Path 'D:\Test' -File -Recurse) | Where-Object { $_.BaseName -match '[-.]' } |
Rename-Item -NewName {'{0}{1}' -f ($_.BaseName -replace '[-.](\d)', '$1'), $_.Extension} -WhatIf
Note: I have added switch -WhatIf for safety so you can first see what would happen in the console. When you are satisfied with that, remove the -WhatIf switch and run again to actually start renaming the files.
switch -Recurse lets Get-ChildItem also find files in subfolders
This is my first post to Stack Overflow, and I avoided asking for help and tried to figure this out as much as I could on my own. I have very little scripting experience, but I'm looking to learn. I chose this project as a place to start, and felt like my goals for this script got out of hand rather quickly.
What I have is a functional, probably very bloated, script, that only does a fraction of what I wanted it to do for me.
Here is the task I have, that before we were doing 100% by hand - manually file by file:
I have MP3 files of high importance that need to get copied off of an SD card and eventually moved to a shared drive that is backed up regularly.
These files are in the file name format of MMDDYYYYHHMMSS_RC-700R.mp3
We store these files on our data share in its own directory, organized further by the month, leading me try to add that in as part of my script, but it is a less important feature.
My goal was to safely move these files off of the SD card, rename them - removing the TIME of the file, but if there were 2 (or more) files made on the same date to append an alphabetical iterative count up. I tried to comment out every step, not only for others to read, but to keep myself apprised of what I was trying to accomplish in each section of the code.
#Start by Clearing Host and Saving Transcript
Clear-Host
$date = Get-Date -Format 'dddd MM-dd-yyyy'
Start-Transcript -Path "F:\Script$date.txt" -NoClobber -Append
#Set locations - SD Card:Import
$Import = "C:\Users\Death\Desktop\Minutes"
$Source = "F:\Minutes\"
$Destination = "F:\Final\"
#Test if $Source Exists, if not Create directory for Files to be transferred to
if(!(Test-Path -Path $Source)) {
New-Item -ItemType directory -Path $Source
Write-Host "Folder path has been created successfully at: " $Source
}
else {
Write-Host "The given folder path $Source already exists";
}
#Test if $Destination exists and create if false
if(!(Test-Path -Path $Destination)) {
New-Item -ItemType directory -Path $Destination
Write-Host "Folder path has been created successfully at: $Destination "}
else {
Write-Host "The given folder path $Destination already exists";
}
#Copy Items from $Import location
Get-ChildItem -Path $Import -Filter *.mp3 | Copy-Item -Destination $Source
#Rename Files adding Dashes between MM DD YYYY and HHMMSS
Get-ChildItem -Path $Source -Filter *.mp3 | Rename-Item -NewName {$_.Name -Replace ('^\n*(\d{2})(\d{2})(\d{4})(\d{6}).(?:...)(\d{3})\w','TC $1-$2-$3-$4')}
#Move files into $Destination\Year\Month created - Need to add
#Move files into $NewPath\Year\Month created
#Running in to problems with moving the files after they have been renamed - Likely due to
Get-ChildItem -File -Path $Source -Filter '*.mp3' |
ForEach-Object {
$Year = $_.LastWriteTime.Year
$Month = $_.LastWriteTime.Month
$Monthname = (Get-Culture).DateTimeFormat.GetMonthName($Month)
$ArchDir = "$Destination\$Year\$Monthname\"
if (-not (Test-Path -Path $ArchDir)) { New-Item -ItemType "directory" -Path $ArchDir | Out-Null }
Move-Item -Path $Source\*.mp3 -Destination $ArchDir -Verbose
}
#Would like to add a list of files renamed and where they moved to instead of just Enter to exit
Read-Host -Prompt "Press Enter to exit"
I have had little parts of my goals working in other versions of this code, but this is my most functional one.
Problems that currently exist:
I haven't figured out how to safely iterate files created on the same day when renaming files and leaving off the TIME - So as it is currently functioning I have it leaving the TIME on the file and I am manually removing it and adding any letters when needed
It is throwing all of the files in to $Destination in the Month of the first file, and putting all the files in there (not a huge issue as this was extra)
I would like it to list every move operation as well as any errors. It is doing this now with the $Source & $Destination folders & the -Verbose on the final GCI - Move operation.
Until I demonstrate that the script is 100% functional I have all locations in the script on my local machine to keep my boss happy.
I am sorry for the wall of text & Thanks in advance for any assistance.
This looks way over-complicated.
For the file parts, it could be as simple as this...
As per your stated use case:
My goal was to safely move these files off of the SD card,
rename them - removing the TIME of the file,
Clear-Host
$SourcePath = 'C:\Temp'
$TargetPath = 'C:\Temp\TempChild'
Get-ChildItem -Path $SourcePath -Filter '*.mp3' |
ForEach {
$FileName = $PSItem
Try
{
If ((Get-Item -Path "$TargetPath\$($FileName.Name)" -ErrorAction Stop))
{
Rename-Item -Path "$TargetPath\$($PSItem.Name)" -NewName "$($FileName.Name -replace '\d+_')" -WhatIf
Move-Item -Path $FileName.FullName -Destination $TargetPath -WhatIf
}
}
Catch {Move-Item -Path $FileName.FullName -Destination $TargetPath -WhatIf}
}
# Results
<#
# When the file does not exists
What if: Performing the operation "Move File" on target "Item: C:\Temp\04122021143000_RC-M1234R.mp3 Destination: C:\Temp\TempChild\04122021143000_RC-M1234R.mp3".
# When the file exists
What if: Performing the operation "Rename File" on target "Item: C:\Temp\TempChild\04122021143000_RC-M1234R.mp3 Destination: C:\Temp\TempChild\RC-M1234R.mp3".
What if: Performing the operation "Move File" on target "Item: C:\Temp\04122021143000_RC-M1234R.mp3 Destination: C:\Temp\TempChild\04122021143000_RC-M1234R.mp3".
#>
You can create new paths, without using New-Item. Just use the -Force switch/parameter on the copy/move action.
Test-Path -Path "$TargetPath\test1"
# Results
<#
False
#>
Get-ChildItem -Path $SourcePath -Filter '*.mp3' |
Copy-Item -Destination "$TargetPath\test1" -Force -WhatIf
# Results
<#
What if: Performing the operation "Copy File" on target "Item: C:\Temp\04122021143000_RC-M1234R.mp3 Destination: C:\Temp\TempChild\test1".
#>
Get-ChildItem -Path $SourcePath -Filter '*.mp3' |
Copy-Item -Destination "$TargetPath\test1" -Force
Test-Path -Path "$TargetPath\test1"
Get-ChildItem -Path $TargetPath -Filter '*.mp3'
# Results
<#
True
Directory: C:\Temp\TempChild
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 4/8/2021 6:04 PM 39 04122021143000_RC-M12345R.mp3
-a---- 4/8/2021 6:04 PM 39 04122021143000_RC-M1234R.mp3
#>
As for
but if there were 2 (or more) files made on the same date to append an alphabetical iterative count up.
I am not sure why you use alpha vs numeric. Since alpha would limit you to 26 letters before you'd end up having to double that string. Numeric of course, you can just look at the number and increment by 1.
Here's what I mean, just using your file name vs file properties. Yet, you can do the same approach, by looking at the file properties in the mix.
Clear-Host
$SourcePath = 'C:\Temp'
$TargetPath = 'C:\Temp\TempChild'
Get-ChildItem -Path $SourcePath -Filter '*.mp3' |
ForEach {
$FileName = $PSItem
Try
{
If (
-Not ((Get-ChildItem -Path $TargetPath -Filter $FileName.Name) -match "(?<=RC-M\d+R\d)") -and
($FileName.Name -replace '_\.*') -match
((Get-ChildItem -Path $TargetPath -Filter $FileName.Name) -replace '_\.*')
)
{
Rename-Item -Path "$TargetPath\$($FileName.Name)" -NewName "$(
$FileName.Name -replace 'R\.', 'R1.'
)" -ErrorAction Stop -WhatIf
Move-Item -Path $FileName.FullName -Destination $TargetPath -Verbose -WhatIf
}
}
Catch
{
$FileToIncrement = (
Get-ChildItem -Path $TargetPath |
Where-Object -Property Name -Match ($FileName.BaseName -replace 'R\d+')
).FullName
if($FileToIncrement -match "(?<=RC-M\d+R)(?<bv>\d+)")
{
Rename-Item -Path $FileToIncrement -NewName (
$FileToIncrement -replace "(?<=RC-M\d+R)(\d+)",
("{0:0000}" -f (([int]::Parse($matches.bv)+1)))
) -Verbose -WhatIf
Move-Item -Path $FileName.FullName -Destination $TargetPath -Verbose -WhatIf
}
}
}
# Results - when incrementer does not exist for the matched time string
<#
VERBOSE: Performing the operation "Rename File" on target "Item: C:\Temp\TempChild\04122021143000_RC-M12345R.mp3 Destination: C:\Temp\TempChild\04122021143000_RC-M12345R1.mp3".
VERBOSE: Performing the operation "Move File" on target "Item: C:\Temp\04122021143000_RC-M12345R.mp3 Destination: C:\Temp\TempChild\04122021143000_RC-M12345R.mp3".
VERBOSE: Performing the operation "Rename File" on target "Item: C:\Temp\TempChild\04122021143000_RC-M1234R.mp3 Destination: C:\Temp\TempChild\04122021143000_RC-M1234R1.mp3".
VERBOSE: Performing the operation "Move File" on target "Item: C:\Temp\04122021143000_RC-M1234R.mp3 Destination: C:\Temp\TempChild\04122021143000_RC-M1234R.mp3".
#>
# Results - when incrementer exists for the matched time string
<#
What if: Performing the operation "Rename File" on target "Item: C:\Temp\TempChild\04122021143000_RC-M12345R1.mp3 Destination: C:\Temp\TempChild\04122021143000_RC-M12345R0002.mp3".
What if: Performing the operation "Move File" on target "Item: C:\Temp\04122021143000_RC-M12345R.mp3 Destination: C:\Temp\TempChild\04122021143000_RC-M12345R.mp3".
What if: Performing the operation "Rename File" on target "Item: C:\Temp\TempChild\04122021143000_RC-M1234R1.mp3 Destination: C:\Temp\TempChild\04122021143000_RC-M1234R0002.mp3".
What if: Performing the operation "Move File" on target "Item: C:\Temp\04122021143000_RC-M1234R.mp3 Destination: C:\Temp\TempChild\04122021143000_RC-M1234R.mp3".
#>
I'm trying to rename about 500 files in a single directory. Each file is .docx format similar to the below.
Apartment_7-9_01_92.docx
Apartment_7-9_02_192.docx
etc.
I want to remove the last two/three digits before the '.', including the '_' so that I end up with
Apartment_7-9_01.docx
Apartment_7-9_02.docx
Having never really used Powershell, the research I've done so far leads me to something like the below:
Get-ChildItem -File | ForEach-Object { $_ | Rename-Item -NewName -Replace $_.Name.SubString(0, $_.lastIndexOf('_')),".docx"}
I would have thought this would take everything, including and after the last '_' and replace it with '.docx', but it's telling me the lastIndexOf method doesn't exist in this case.
Thanks
I fixed your code, but I don't think it does what you want. $_ is a fileinfo object, and $_.name is a string, and .lastindexof() is a string method. I think you want to replace a substring location after the last "_", not before it.
Get-ChildItem -File | ForEach-Object { $_ | Rename-Item -NewName (
$_.name -Replace $_.Name.SubString(0, $_.Name.lastIndexOf('_')),".docx") -whatif}
What if: Performing the operation "Rename File" on target "Item:
/Users/js/Apartment_7-9_01_92.docx Destination: /Users/js/.docx_92.docx".
What if: Performing the operation "Rename File" on target "Item:
/Users/js/Apartment_7-9_02_192.docx Destination: /Users/js/.docx_192.docx".
This seems to work, and is close to what you were trying. Just specify where the substring starts.
Get-ChildItem -File | ForEach-Object { $_ | Rename-Item -NewName (
$_.name -Replace $_.Name.SubString($_.Name.lastIndexOf('_')),".docx") -whatif}
What if: Performing the operation "Rename File" on target "Item:
/Users/js/Apartment_7-9_01_92.docx Destination:
/Users/js/Apartment_7-9_01.docx".
What if: Performing the operation "Rename File" on target "Item:
/Users/js/Apartment_7-9_02_192.docx Destination:
/Users/js/Apartment_7-9_02.docx".
There's a way to pipe directly to rename-item too, like in the docs:
Get-ChildItem -File | Rename-Item -NewName {
$_.name -Replace $_.Name.SubString($_.Name.lastIndexOf('_')),".docx"} -whatif
You could first split the BaseName on "_", then take every item except the last and rejoin back on "_". An easy way to do that is with $array[0..($array.Length - 2)]. You could also just do $array[0..2] to take the first 3 items. You can then add the Extension at the end. From here you can simply rename the FullName with Rename-Item.
$Path = "PATH/TO/FILES"
Get-ChildItem -Path $Path -File | ForEach-Object {
$items = $_.BaseName -split "_"
$newFileName = ($items[0..($items.Length - 2)] -join "_") + $_.Extension
Rename-Item -Path $_.FullName -NewName $newFileName
}
I'm looking for help restructuring a large number of files within many subfolders.
Example source:
folderX
aaa.txt
bbb.txt
folderY
ccc.txt
folderZ
ddd.txt
eee.txt
Ideal result:
folderX_aaa.txt
folderX_aaa.txt
folderX_bbb.txt
folderY_ccc.txt
folderY_folderZ_ddd.txt
eee.txt
I hope that makes sense! I'm using Plex to manage some media and it doesn't like subfolders for certain uses (eg featurettes directory).
I'd like to use PowerShell because I'm already kinda familiar with it - but any techniques or suggestions are welcome.
Thanks in advance :)
Here's a single-pipeline solution:
$targetDir = Convert-Path '.' # Get the current (target) directory's full path.
Get-ChildItem -LiteralPath $targetDir -Directory | # Loop over child dirs.
Get-ChildItem -Recurse -File -Filter *.txt | # Loop over all *.txt files in subtrees of child dirs.
Move-Item -Destination { # Move to target dir.
# Construct the full target path from the target dir.
# and the relative sub-path with path separators replaced with "_" chars.
Join-Path $targetDir `
($_.Fullname.Substring($targetDir.Length + 1) -replace '[/\\]', '_')
} -Whatif
-WhatIf previews the move operations; remove it to perform actual moving.
Regex [/\\] matches / or \ as the path separator, so as to make the solution cross-platform.
while it would have been nice if you had shown what you have tried, i got interested ... [grin]
what the code does ...
sets some constants
creates some files & dirs to work with
grabs the files that match the target location & type
skips any file that is already in the $TopDir
derives the old file & dir names
uses the above to make a new full file name
moves the items
this only shows what WOULD happen. remove the -WhatIf to do it for real.
please note that the code DOES NOT check to see if there are same-named files in the destination.
the code itself ...
$TopDir = "$env:TEMP\PlexStuff"
$Delimiter = '_-_'
$Filter = '*.txt'
#region >>> create some files to test with
# remove this region after you have tested it
#(
[System.IO.FileInfo]"$TopDir\OneThing\aaa.txt"
[System.IO.FileInfo]"$TopDir\OneThing\bbb.txt"
[System.IO.FileInfo]"$TopDir\TwoThing\aaa.txt"
[System.IO.FileInfo]"$TopDir\ThreeThing\ccc.txt"
[System.IO.FileInfo]"$TopDir\ThreeThing\ddd.txt"
[System.IO.FileInfo]"$TopDir\eee.txt"
) |
ForEach-Object {
# the "$Null =" suppresses unwanted output from the commands
$Null = mkdir $_.Directory.FullName -Force -ErrorAction SilentlyContinue
$Null = New-Item -Path $_.Directory.FullName -Name $_.Name -ItemType File -ErrorAction SilentlyContinue
}
#endregion >>> create some files to test with
$FileList = Get-ChildItem -LiteralPath $TopDir -File -Recurse -Filter $Filter
foreach ($FL_Item in $FileList)
{
# skip files that are in the TopDir
if (-not ($FL_Item.DirectoryName -eq $TopDir))
{
$OldFileName = $FL_Item.Name
$OldDirName = $FL_Item.DirectoryName
$NewFileName = ($OldDirName, $OldFileName) -join $Delimiter
Move-Item -LiteralPath $FL_Item.FullName -Destination $NewFileName -WhatIf
}
}
output [slightly reformatted for readability] ...
What if: Performing the operation "Move File" on target "Item: C:\Temp\PlexStuff\OneThing\aaa.txt
Destination: C:\Temp\PlexStuff\OneThing_-_aaa.txt".
What if: Performing the operation "Move File" on target "Item: C:\Temp\PlexStuff\OneThing\bbb.txt
Destination: C:\Temp\PlexStuff\OneThing_-_bbb.txt".
What if: Performing the operation "Move File" on target "Item: C:\Temp\PlexStuff\ThreeThing\ccc.txt
Destination: C:\Temp\PlexStuff\ThreeThing_-_ccc.txt".
What if: Performing the operation "Move File" on target "Item: C:\Temp\PlexStuff\ThreeThing\ddd.txt
Destination: C:\Temp\PlexStuff\ThreeThing_-_ddd.txt".
What if: Performing the operation "Move File" on target "Item: C:\Temp\PlexStuff\TwoThing\aaa.txt
Destination: C:\Temp\PlexStuff\TwoThing_-_aaa.txt".
I have a folder structure that I'd like to go through and any time the folder name contains "&", I'd like to replace this with the word "and". I assume this is possible with powershell, but I am extreme noobie when it comes to PowerShell.
Thanks!
Here is my attempt:
get-childitem -recurse ./ *&* | where-object { $_.Name -like "*&*" } | % {rename-item $_ -newname $_.Name.Replace("&","and") -whatif}
will this only change the folder names?
Also tried this one but no luck either (This one gives the error: Cannot rename because the target specified represents a path or device name:
gci -recurse | where-object { $_.Name -like "*&*" } | ?{ $_.PSIsContainer } | % {rename-item $_FullName $_FullName.Replace("&","and")}
EDIT: POWERSHELL on Windows Server 2008 R2
I suspect one reason the original code fails is because Rename-Item is being given a NewName parameter which includes the entire path, rather than just the name. Secondary problem here is that the code will try to rename from the top down, which may invalidate other objects in the pipeline. I've tried to get around this by processing the longest paths first (hence descending sort on PSPath.length). It worked on my test folders.
get-childitem ./ -Recurse -Filter "*&*" |
? { $_.PSIsContainer } |
sort { ($_.PSPath).length } -Descending |
% {
$_ | Rename-Item -NewName ($_.Name -replace "&","and")
}
The reason for your error is that you replace the & character in the whole path, even parent folders.
Say for example that you want to rename the folder c:\me & my\something & another your $_.FullName.Replace("&", "and") would change that to c:\me and my\something and another. However, since we in this little test scenario renamed the subfolder before the parent folder we're actually trying to move the folder from being a child of c:\my & my to being a child of c:\me and my (and on top of that we want to move it to a folder which doesn't exist.
From the help section on Rename-Item (which I got by executing Get-Help Rename-Item -Parameter NewName):
Specifies the new name of the item. Enter only a name, not a path and name. If you enter a path that is different
from the path that is specified in the Path parameter, Rename-Item generates an error. To rename and move an item,
use the Move-Item cmdlet.
So we only want to include the name of the folder in the NewName parameter.
Finally, as #andyb pointed out, we also need to rename the items in the order of subfolder, then parent folder, to ensure that the parent path is still intact. #andyb's suggested solution of sorting the folders by the length of the FullName path should work well for this.
Thus the following should work very well.
Get-ChildItem .\ -Recurse -Filter "*&*" |
Where { $_.PSIsContainer } |
Sort { $_.FullName.Length } -Descending |
Foreach {
$newName = $_.Name.Replace("&", "and")
Rename-Item $_.FullName $newName
}
Edit: Updated to include sorting in folder path length descending order, due to a misstake which #andyb pointed out.
You are on the right path. Created a couple of test folders and files under 'C:\temp\aaa' folder to show how it works
PS C:\> gci C:\Temp\aaa -recurse | where {$_.name -match '&'} | Rename-Item -newname {$_.name -replace '&','and'} -whatif
What if: Performing the operation "Rename Directory" on target "Item: C:\Temp\aaa\ad & il Destination: C:\Temp\aaa\ad and il".
What if: Performing the operation "Rename Directory" on target "Item: C:\Temp\aaa\ad & il\hin\di&st&t Destination: C:\Temp\aaa\ad & il\hin\diandstandt".
What if: Performing the operation "Rename File" on target "Item: C:\Temp\aaa\ad & il\hin\adilll&hindist &an.txt Destination: C:\Temp\aaa\ad & il\hin\adilllandhi ndist andan.txt".
Steps:
1. match items
reverse items so that we can rename them from child to parent
rename them
Code:
$matchedItems = ls D:\test -Recurse | where { $_.Name -like '*&*' }
[array]::Reverse( $matchedItems )
$matchedItems | foreach {
$newName = ""
if($_.PSIsContainer){
$newName = Join-Path $_.Parent.FullName ($_.BaseName -replace '&' , 'and')
}
else {
$newName = Join-Path $_.Directory.FullName ($_.BaseName -replace '&' , 'and')
}
$_ | Rename-Item -NewName $newName
}
Output:
PS C:\> ls D:\test -Recurse | select FullName
FullName
--------
D:\test\& New Foder
D:\test\New & folder
D:\test\New folder&
D:\test\test & test.txt
D:\test\& New Foder\New & folder
D:\test\& New Foder\New folder&
D:\test\& New Foder\test & test.txt
D:\test\New folder&\& New Foder
D:\test\New folder&\New & folder
D:\test\New folder&\New folder&
D:\test\New folder&\test & test.txt
D:\test\New folder&\& New Foder\New & folder
D:\test\New folder&\& New Foder\New folder&
D:\test\New folder&\& New Foder\test & test.txt
PS C:\> $matchedItems = ls D:\test -Recurse | where { $_.Name -like '*&*' }
[array]::Reverse( $matchedItems )
$matchedItems | foreach {
$newName = ""
if($_.PSIsContainer){
$newName = Join-Path $_.Parent.FullName ($_.BaseName -replace '&' , 'and')
}
else {
$newName = Join-Path $_.Directory.FullName ($_.BaseName -replace '&' , 'and')
}
$_ | Rename-Item -NewName $newName
}
PS C:\> ls D:\test -Recurse | select FullName
FullName
--------
D:\test\and New Foder
D:\test\New and folder
D:\test\New folderand
D:\test\test and test
D:\test\and New Foder\New and folder
D:\test\and New Foder\New folderand
D:\test\and New Foder\test and test
D:\test\New folderand\and New Foder
D:\test\New folderand\New and folder
D:\test\New folderand\New folderand
D:\test\New folderand\test and test
D:\test\New folderand\and New Foder\New and folder
D:\test\New folderand\and New Foder\New folderand
D:\test\New folderand\and New Foder\test and test