I have a beginner script. I'm new to Powershell.
It goes into a large directory tree, then recurses through it, getting identical fies and deleting the duplicates.
I want to add some more information to it's output:
- I want to accrue the size of each recurs'd duplicate
- Print out the size at the end (probably MB or GB)
# Specify the folder to search
$FolderPath = "C:\Users\Ben\Music\Apple Music\Media\Music\"
# Get all files in the specified folder and subfolders
$Files = Get-ChildItem -Path $FolderPath -Recurse -File
# Group files by their hash (to identify duplicates)
$Files | Get-FileHash | Group-Object -Property Hash | Where-Object { $_.Count -gt 1 } | ForEach-Object {
# For each group of duplicate files
foreach ($DuplicateFile in $_.Group) {
# Skip the first file in the group (keep one copy)
if ($DuplicateFile -ne $_.Group[0]) {
# Delete the duplicate file
Write-Host "Deleting: $($DuplicateFile.Path)"
# Remove-Item -Path $DuplicateFile.Path -Force
$fileSize = (Get-ChildItem ($_.Path).Length)
Write-Host ($fileSize | Format-List | Out-String)
$size=$size+$fileSize
}
}
}
Write-Host "deleted $($size/(1024*1024))MB of files."
I've commented out the remove-item line because I wanted to get an idea of what the script was doing without deleting 10K files and being up... a creek.
I get the error:
Deleting: C:\Users\Ben\Music\Apple Music\Media\Music\Music\A Song.mp3
Get-ChildItem: C:\Users\Ben\Documents\DeleteDuplicates.ps1:19
Line |
20 | $fileSize = (Get-ChildItem ($DuplicateFile.Path).Length)
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| Cannot find path 'C:\Users\Ben\Documents\140' because it does not exist.
deleted 0MB of files.
Press Enter to continue...:
What's going wrong?
I've written this for Powershell 7.5
I'm aware it's highly inefficient but you gotta start somewhere.
I have a beginner script. I'm new to Powershell.
It goes into a large directory tree, then recurses through it, getting identical fies and deleting the duplicates.
I want to add some more information to it's output:
- I want to accrue the size of each recurs'd duplicate
- Print out the size at the end (probably MB or GB)
# Specify the folder to search
$FolderPath = "C:\Users\Ben\Music\Apple Music\Media\Music\"
# Get all files in the specified folder and subfolders
$Files = Get-ChildItem -Path $FolderPath -Recurse -File
# Group files by their hash (to identify duplicates)
$Files | Get-FileHash | Group-Object -Property Hash | Where-Object { $_.Count -gt 1 } | ForEach-Object {
# For each group of duplicate files
foreach ($DuplicateFile in $_.Group) {
# Skip the first file in the group (keep one copy)
if ($DuplicateFile -ne $_.Group[0]) {
# Delete the duplicate file
Write-Host "Deleting: $($DuplicateFile.Path)"
# Remove-Item -Path $DuplicateFile.Path -Force
$fileSize = (Get-ChildItem ($_.Path).Length)
Write-Host ($fileSize | Format-List | Out-String)
$size=$size+$fileSize
}
}
}
Write-Host "deleted $($size/(1024*1024))MB of files."
I've commented out the remove-item line because I wanted to get an idea of what the script was doing without deleting 10K files and being up... a creek.
I get the error:
Deleting: C:\Users\Ben\Music\Apple Music\Media\Music\Music\A Song.mp3
Get-ChildItem: C:\Users\Ben\Documents\DeleteDuplicates.ps1:19
Line |
20 | $fileSize = (Get-ChildItem ($DuplicateFile.Path).Length)
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| Cannot find path 'C:\Users\Ben\Documents\140' because it does not exist.
deleted 0MB of files.
Press Enter to continue...:
What's going wrong?
I've written this for Powershell 7.5
I'm aware it's highly inefficient but you gotta start somewhere.
Share Improve this question asked Mar 31 at 23:09 Benjamin RichBenjamin Rich 211 silver badge4 bronze badges2 Answers
Reset to default 2I think your brackets are misaligned:
$fileSize = (Get-ChildItem ($DuplicateFile.Path).Length)
This gets the Length
property of $DuplicateFile.Path
which, in your example, I presume is 140 characters, so it tries to get the item named 140
.
Just replace with:
$fileSize = (Get-ChildItem $DuplicateFile.Path).Length
Use Get-ItemPropertyValue
to grab the Length
property per file:
$Files | Get-FileHash | Group-Object -Property Hash | Where-Object { $_.Count -gt 1 } | ForEach-Object {
foreach ($DuplicateFile in $_.Group |Select-Object -Skip 1) {
$fileSize = Get-ItemPropertyValue -LiteralPath $duplicateFile.Path -Name Length
Write-Host "Duplicate file at '$($duplicateFile.Path)' size: $($fileSize) bytes"
# Remove-Item -Path $DuplicateFile.Path -Force
$size += $fileSize
}
}
Here I'm deliberately using the -LiteralPath
parameter to pass the file path, to avoid wildcard expansion - if you were to pass a path like C:\path\with[square]brackets\file.ext
to the -Path
parameter it would otherwise interpret [square]
as a wildcard macro