Deleting files with Powershell recursively - powershell

I got somehow a weird issue, I am trying to use a process to automate the deletion of files from a folder and also child folders, I am trying to delete only files older than 7 days.
My code works but it deletes files that are under 7 days when going recursively into child items. . .anyone could lend a hand here? I just need to delete in each folder/sub-folder the files older than 7 days.
Param (
[string]$Source = "C:\Users\Loredanes\Downloads\",
[string]$Days = "1"
)
$Files = Get-ChildItem $Source -Recurse | Where-Object { !$_.PSIsContainer -and $_.LastWriteTime -lt (get-date).addminutes(-$($Days)) }
$Files | Remove-Item -Force
if ($Files.count -gt 0)
{
$Folders = #()
ForEach ($Folder in (Get-ChildItem -Path $Source -Recurse -Directory))
{
$Folders += New-Object PSObject -Property #{
Object = $Folder
Depth = ($Folder.FullName.Split("\")).Count
}
}
$Folders = $Folders | Sort Depth -Descending
ForEach ($Folder in $Folders)
{
If ($Folder.Object.GetFileSystemInfos().Count -eq 0)
{
Write-Host "Removing Folder: $($Folder)"
Remove-Item -Path $Folder.Object.FullName -Force
}
}
}
else
{
Write-Host "No Empty folders found after removing files older than $($Days) days."
}

This should do what you want:
$source = 'D:\Test'
$days = 7
# Remove Files
Get-ChildItem $Source -Recurse | Where-Object { !$_.PSIsContainer -and $_.LastWriteTime -lt (get-date).AddDays(-$($days)) } | % { Remove-Item -Path $_.FullName -Force }
# Remove empty directories
Get-ChildItem $source -Recurse | Where-Object { $_.PSIsContainer -and $_.GetFiles("*.*").Count -le 0 } | % { Remove-Item -Path $_.FullName -Force }

Related

Post-order Traverse in PowerShell recurse

Get-ChildItem -Recurse in powershell currently traverse a directory in level order fashion. Is there any way to traverse a directory in post-order way in Powershell?
I am trying to delete files which are older than certain times. and after deleting files, if subfolder is empty, delete that folder too. Right now am doing this.
$path = 'D:\Files'
Get-ChildItem -Path $path -Recurse | Where-Object {
(($_.LastWriteTime -lt (Get-Date).AddDays(-30)) -and ($_ -is [system.io.fileinfo]) )
} | Remove-Item
Get-ChildItem -Path $path -Recurse | Where-Object {
($_ -is [System.IO.DirectoryInfo]) -and $_.CreationTime -lt (Get-Date).AddDays(-30) -and ((Get-ChildItem $_.FullName).Count -eq 0)
} | Remove-Item -Force
But I want to do it in a single command. Not as two different command.
You could reverse the order of the items returned by Get-ChildItem with [Array]::Reverse
Full script:
$items = Get-ChildItem 'D:\Files' -Recurse
[Array]::Reverse($items)
$date = (Get-Date).AddDays(-30)
foreach ($item in $items) {
if ($item.PSIsContainer) {
if ($item.CreationTime -lt $date -and (Get-ChildItem $item.FullName).Count -eq 0) {
Remove-Item $item.FullName
}
}
elseif ($item.LastWriteTime -lt $date) {
Remove-Item $item.FullName
}
}
I couldn't get the post order working properly with GCI, someone claimed it should, but it wasn't traversing depth first. Below is a naive implementation of the classic post order algorithm using the push directory and pop directory commands. Put your "actions" where Write-Host is.
function PostOrder($d){
pushd $d
$folders = Get-ChildItem .\ -Directory -Force
foreach ($folder in $folders){
PostOrder($folder)
}
popd
Write-Host $d.FullName
}
PostOrder("C:\myFolder")

Moves files into new subfolder for each year/month

I am trying to move all files under each subfolder into another folder with subfoldername_mmm_yyyy name.
Below codes only move all files in all sub folders into one folder with the name subfoldername_subfoldername_mmm_yyyy.
I know my for each loops are incorrect but I don't know how to fix them, would someone please help?
$curr_date = Get-Date
$folder_path = "C:\Logs\"
$file_type = "C:\Logs\*.log*"
$destination = "C:\Archive\"
# delete tmp files if existed
$deletefile = Get-ChildItem $destination -recurse -include *.7z.tmp -force | remove-item
# set min age of files
$max_days = "-1"
# determine how far back we go based on current date
$zip_date = $curr_date.AddDays($max_days)
Get-ChildItem -Path $folder_path | Where-Object { $_.Attributes -eq "Directory" } | foreach {
# obtain all subfolders
$servername = Get-ChildItem -Path $folder_path | Where-Object { $_.Attributes -eq "Directory" }
# move all files into servername_mmm_yyyy folder
Get-ChildItem $file_type -Recurse | Where-Object { ($_.LastWriteTime -lt $zip_date) -and ($_.psIsContainer -eq $false)}| foreach {
$x = $_.LastWriteTime.ToShortDateString()
$month_year = Get-Date $x -Format MMM_yyyy
$file_destination = ($destination) + ($servername) + "_" + ($month_year)
if (test-path $file_destination) {
move-item $_.fullname $file_destination
}
else {
new-item -ItemType directory -Path $file_destination
move-item $_.fullname $file_destination
}
}
}
Change:
Get-ChildItem $file_type -Recurse | Where-Object { ($_.LastWriteTime -lt $zip_date) -and ($_.psIsContainer -eq $false)} ...
to
Get-ChildItem $file_type -Recurse | Where-Object { ($_.LastWriteTime -lt $zip_date) -and ($_.psIsContainer -eq $false) -and $_.Name.EndsWith(".log")}
and that should get you just the files you want to target
I figured out my problem. Here is how I do it.
I just need to obtain the folder name of each file and build the destination path. Therefore, I only need one foreach loop.
# move all files into servername_mmm_yyyy folder
Get-ChildItem $file_path -Recurse | Where-Object { ($_.LastWriteTime -lt $zip_date) -and ($_.psIsContainer -eq $false)}| foreach {
$x = $_.LastWriteTime.ToShortDateString()
$month_year = Get-Date $x -Format MMM_yyyy
$servername = $_.Directory.Name
$file_destination = ($destination)+($servername)+"_"+($month_year)
if (test-path $file_destination){
copy-item $_.fullname $file_destination
}
else {
new-item -ItemType directory -Path $file_destination
copy-item $_.fullname $file_destination
}
}

How can I delete files older than x days?

I want to delete files older than x days, 5 in the below example. I tried to use below, but its not working nor its throwing an error.
Get-ChildItem –Path “E:\del” –Recurse | Where-Object{$_.CreationTime –lt(Get-Date).AddDays(-5)} | Remove-Item
Here is an approach you could take.
$Path = E:\del
$DaysBack = "-5"
$CurrentDate = Get-Date
$DatetoDelete = $CurrentDate.AddDays($DaysBack)
#delete files from $Path directory that are older than $Daysback
Get-ChildItem -Path $Path -Include * -Recurse | Where-Object {$_.LastWriteTime -lt $DatetoDelete} | Remove-Item -ErrorAction SilentlyContinue -Recurse -Force
Try this:
$cleanup_days = 5
$cleanup_lastWrite = $now.AddDays(-$cleanup_days)
Get-ChildItem -Path "E:\del" | Where-Object { $_ -is [System.IO.FileInfo] } | ForEach-Object {
If ($_.LastWriteTime -lt $cleanup_lastWrite)
{
Remove-Item $("E:\del\" + $_)
}
}

Powershell delete Folder if all Files older than x days

I'm new at PowerShell and don't know so much about it.
I'm searching for a way to delete a folder and all sub-folders if all files in this are older than x days. I have an code to delete all files in a folder and all sub-folders but I don't know how to change it right.
$Now = Get-Date
$Days = "30"
$TargetFolder = "C:\temp"
$Extension = "*.*"
$LastWrite = $Now.AddDays(-$Days)
$Files = Get-Childitem $TargetFolder -Include $Extension -Recurse | Where {($_.CreationTime -le "$LastWrite") -and ($_.LastWriteTime -le "$LastWrite")}
foreach ($File in $Files)
{
if ($File -ne $NULL)
{
write-host "Deleting File $File" -ForegroundColor "Red"
Remove-Item $Location.FullName | out-Null
}
else
{
Write-Host "No more files to delete!" -foregroundcolor "Green"
}
}
Enumerate all folders and sort them longest path first, so you process the directories bottom to top:
Get-ChildItem $TargetFolder -Recurse -Directory |
Select-Object -Expand FullName |
Sort-Object Length -Desc
Filter the list for directories that don't have any file or folder newer than x days in them:
... | Where-Object {
-not $(Get-ChildItem $_ -Recurse | Where-Object {
$_.Creationtime -ge $LastWrite -or
$_.LastWriteTime -ge $LastWrite
})
}
Then remove the resulting folders:
... | Remove-Item -Recurse -Force

Powershell Cleanup script. Excluded folder not being excluded

I wrote a simple script that will run as a scheduled task every weekend. This script cleans up files older than # days and you can give the name of a folder for exclusion as a parameter. This folder should not be cleaned up by the script. But somehow the script still deletes some files from the excluded folder. But in a strange way no files matching the conditions of the parameter.
For example I run the script to delete files older than 15 days and exclude the folder NOCLEANUP. but some files still get deleted from that folder, but there are still files older than 15 days in the NOCLEANUP folder.
Code below
Thanks in advance and apologies for the dirty code. Still new to PS.
Function CleanDir ($dir, $days, $exclude, $logpath)
{
$Limit = (Get-Date).AddDays(-$days)
$Path = $dir
#Folder to exclude
$ToExclude = $exclude
#Log location
$Log= $logpath
$Testpath = Test-Path -PathType Container -Path $Log
if ($Testpath -ne $true)
{
New-Item -ItemType Directory -Force -Path $Log
}
#Logs deleted files
cd $Log
Get-ChildItem -Path $Path -Recurse -Force | Where-Object { !$_.PSIsContainer -and $_.LastwriteTime -lt $Limit } | Where-Object { $_.fullname -notmatch $ToExclude} | Where-Object { $_.fullname -notmatch '$RECYCLE.BIN'} | Out-File -FilePath CLEANUPLOG.TXT
# Delete files older than the $Limit.
Get-ChildItem -Path $Path -Recurse -Force | Where-Object { !$_.PSIsContainer -and $_.LastwriteTime -lt $Limit } | Where-Object { $_.fullname -notlike $ToExclude} | Remove-Item -Force -Recurse
#Goes into every folder separately and deletes all empty subdirectorys without deleting the root folders.
$Folder = Get-ChildItem -Path $Path -Directory
$Folder.fullname | ForEach-Object
{
Get-ChildItem -Path $_ -Recurse -Force | Where-Object {$_.PSIsContainer -eq $True} | Where-Object {$_.GetFiles().Count -eq 0} | Remove-Item -Force -Recurse
}
}