Delete old files from a big folder with powershell - powershell

I have a very big folder (contains subfolders in few levels, millions of files in total). I want to only deletes files that are older than X days (eg 10 days).
My script below works fine for a folder with thousands of files, but is not working for that big folder. Any idea to optimize this? Thanks !
$tmpList = Get-ChildItem -Path $sourceFolder -Recurse
$fileObjects = $tmpList `
| Where-Object { !$_.PSIsContainer -and ($_.LastWriteTime -le $maxDateToProcess) } `
| Sort-Object -Property "LastWriteTime" -Descending
$allFiles = $fileObjects | Select -ExpandProperty "FullName"
Remove-Item -Path $allFiles

Type the following command to delete files that haven’t been modified in the last 30 days and press Enter:
Get-ChildItem –Path "C:\path\to\folder" -Recurse | Where-Object {($_.LastWriteTime -lt (Get-Date).AddDays(-30))} | Remove-Item

Related

How to skip a folder and its sub-folder and files from getting deleted using PowerShell?

I have a PS script which deletes the folders and files from a particular path older than 15 days.
I want to exclude "_tasks" folder and its contents from getting deleted but the scripts deletes the files and folders inside it even when I have provided -Exclude property to exclude _tasks folder and its contents.
Below is the script I am using.
How can I exclude the _tasks folder and its sub-folders and files from getting deleted?
Get-ChildItem –Path "F:\Suraj\Garbage" -Recurse -Exclude "__tasks" |
Where-Object {($_.LastWriteTime -lt (Get-Date).AddDays(-15))} |
Remove-Item -Force -Recurse
Below images shows that the files on the left side were deleted inside the _tasks folders. I don't want them to be deleted. Any suggestion for same would be helpful.
this piece of code selects all files except folder _task and its subfolders..
Get-ChildItem -Path 'F:\Suraj\Garbage' -Recurse |
Select-Object LastWriteTime -ExpandProperty FullName |
Where-Object { ($_ -notlike 'F:\Suraj\Garbage\_tasks*') -and ($_.LastWriteTime -lt (Get-Date).AddDays(-15))} |
Remove-Item -Force -Recurse
or better like Theo's suggest:
Get-ChildItem -Path 'F:\Suraj\Garbage' -Recurse |
Where-Object { ($_.FullName -notlike 'F:\Suraj\Garbage\_tasks*') -and ($_.LastWriteTime -lt (Get-Date).AddDays(-15))} |
Remove-Item -Force -Recurse

powershell - Replace only old files with new files in destination directory

Hello All,
I wish to replace only the old file with new file
I tried
Set-Location C:\contains_newfolder_contents\Old Folder
Get-ChildItem | ForEach-Object {
if ((Test-Path 'C:\contains_newfolder_contents\Sample Folder\$_' ) -and
(.$_.LastWriteTime -gt C:\contains_newfolder_contents\Sample Folder\$_.LastWriteTime' )) {
Copy-Item .\$_ -destination 'C:\contains_newfolder_contents\Sample Folder'
}
}
Kindly correct me!
Here's a one-line solution. I used different folder names to make the example easier to read.
Get-ChildItem C:\temp\destination|foreach-object {$sourceItem = (get-item "c:\temp\source\$($_.name)" -erroraction ignore); if ($sourceItem -and $sourceItem.LastWriteTime -gt $_.lastwritetime) {Copy-Item -path $sourceItem -dest $_.fullname -verbose}}
For each existing file, it finds the matching file in the source folder. $sourcItem will be null if there is no matching source item. It proceeds to compare the dates and copy if the source date is newer.
you can do it too :
Get-ChildItem "C:\contains_newfolder_contents\Old Folder" -file | sort LastWriteTime -Descending | select -First 1 | Copy-Item -Destination 'C:\contains_newfolder_contents\Sample Folder'
Instead of making several reads to the source, I propose you make a lookup table and then these simple commands will achieve the desired results.
$source = 'C:\temp\Source'
$destintation = 'C:\temp\Destination'
$lookup = Get-ChildItem $destintation | Group-Object -Property name -AsHashTable
Get-ChildItem -Path $source |
Where-Object {$_.lastwritetime -gt $lookup[$_.name].lastwritetime} |
Copy-Item -Destination $destintation

PowerShell Script to Delete files from all SubFolders which are older than 30 days

I want to delete all types of Files from below folder structure which is older than 30 Days. So I used below PowerShell Script. But it is not deleting any file.
PowerShell Script:
Get-ChildItem –Path "C:\Users\VJ\Documents\MainDir" –Recurse | Where-Object { $_.CreationTime –lt (Get-Date).AddDays(-30) } | Remove-Item
Folder Structure:
MainDir
|
SubDir1 -> Folder1 -> Folder2 -> Zip/CSV files
SubDir2 -> Folder1->.txt files
|
Folder2 -> .txt files
End Result should be all types of Files deleted from all folders - subfolders of MainDir.
I think you are confusing the properties CreationTime and LastWriteTime.
If you've just copied (old) files to one of the directories in the structure, the CreationTime is the date and time the file was copied there, which can be today. The LastWriteTime property however shows the date and time the file was last written to.
Try:
$refDate = (Get-Date).AddDays(-30)
Get-ChildItem -Path "C:\Users\VJ\Documents\MainDir" -Recurse -File |
Where-Object { $_.LastWriteTime -lt $refDate } |
Remove-Item -Force
If you're on PowerShell version less than 3.0, use:
Get-ChildItem -Path "C:\Users\VJ\Documents\MainDir" -Recurse |
Where-Object { !$_.PSIsContainer -and $_.LastWriteTime -lt $refDate } |
Remove-Item -Force
Also, check and retype your dashes, because they may LOOK like normal hyphens, in fact they are EN Dashes (Hex value 2013; Decimal 8211)
Hope that helps
Try this:
Get-ChildItem -Path "C:\Users\VJ\Documents\MainDir" -Recurse -Force | Where-Object { !$_.PSIsContainer -and $_.CreationTime –lt (Get-Date).AddDays(-30) } | Remove-Item -Force

Powershell Delete Files but keep last x version

I have a folder structure with, for example, 100 folders. Each folder has 200 files in it.
I would like to delete (via scheduled task) all files in each folder but keep the last 10 versions of it.
I am trying to upskill in Powershell so I am guessing that this should be pretty simple. I have created this script,
#Delete all files, keep last 10 versions#
$Directory = "D:\Octopus\Packages"
$Keep = "10"
Get-ChildItem $Directory| ?{ $_.PSIsContainer } | Select-Object FullName | Export-Csv $Directory\FolderList.csv
$FolderList = import-csv $Directory\FolderList.csv
ForEach ($row in $FolderList)
{
Get-ChildItem -Recurse | where{-not $_.PsIsContainer}| sort CreationTime -desc | select -Skip $Keep | Remove-Item -Force
}
It appears to be looping through each folder, but keeping the last 10 files for the entire folder structure, not per folder. So some folders have 0 files, some may have 2 files, some may have 8 files.
Any pointers would be appreciated
Thanks !
If you actually need to have that CSV then just modify Get-ChildItem -Recurse to Get-ChildItem $row -recurse. However, if you don't need to be creating the CSV, you can remove of that and just pipe the results of your first Get-ChildItem into the next action.
$Directory = "D:\Octopus\Packages"
$Keep = "10"
Get-ChildItem $Directory| ?{ $_.PSIsContainer } | Select-Object FullName |
ForEach-object {Get-ChildItem $_.fullname -Recurse |
where{-not $_.PsIsContainer}| sort CreationTime -desc |
select -Skip $Keep | Remove-Item -Force }

Compare-Object Delete File if file does not exist on source

I have this PowerShell code that compares 2 directories and removes files if the files no longer exist in the source directory.
For example say I have Folder 1 & Folder 2. I want to compare Folder 1 with Folder 2, If a file doesn't exist anymore in Folder 1 it will remove it from Folder 2.
this code works ok but I have a problem where it also picks up file differences on the date/time. I only want it to pick up a difference if the file doesn't exist anymore in Folder 1.
Compare-Object $source $destination -Property Name -PassThru | Where-Object {$_.SideIndicator -eq "=>"} | % {
if(-not $_.FullName.PSIsContainer) {
UPDATE-LOG "File: $($_.FullName) has been removed from source"
Remove-Item -Path $_.FullName -Force -ErrorAction SilentlyContinue
}
}
Is there an extra Where-Object {$file1 <> $file2} or something like that.?
I am not sure how you are getting the information for $source and $destination I am assuming you are using Get-ChildItem
What i would do to eliminate the issue with date/time would be to not capture it in these variables. For Example:
$source = Get-ChildItem C:\temp\Folder1 -Recurse | select -ExpandProperty FullName
$destination = Get-ChildItem C:\temp\Folder2 -Recurse | select -ExpandProperty FullName
By doing this you only get the FullName Property for each object that is a child item not the date/time.
You would need to change some of the script after doing this for it to still work.
If I am not getting it wrong, the issue is your code is deleting the file with different time-stamp as compared to source:
Did you try -ExcludeProperty?
$source = Get-ChildItem "E:\New folder" -Recurse | select -ExcludeProperty Date
The following script can serve your purpose
$Item1=Get-ChildItem 'SourcePath'
$Item2=Get-ChildItem 'DestinationPath'
$DifferenceItem=Compare-Object $Item1 $Item2
$ItemToBeDeleted=$DifferenceItem | where {$_.SideIndicator -eq "=>" }
foreach ($item in $ItemToBeDeleted)
{
$FullPath=$item.InputObject.FullName
Remove-Item $FullPath -Force
}
Try something like this
In PowerShell V5:
$yourdir1="c:\temp"
$yourdir2="c:\temp2"
$filesnamedir1=(gci $yourdir1 -file).Name
gci $yourdir2 -file | where Name -notin $filesnamedir1| remove-item
In old PowerShell:
$yourdir1="c:\temp"
$yourdir2="c:\temp2"
$filesnamedir1=(gci $yourdir1 | where {$_.psiscontainer -eq $false}).Name
gci $yourdir2 | where {$_.psiscontainer -eq $false -and $_.Name -notin $filesnamedir1} | remove-item
If you want to compare files in multiple dir, use the -recurse option for every gci command.