3
votes
#----- define parameters -----#
#----- get current date ----#
$Now = Get-Date

#----- define amount of days ----#
$Days = "3"
#----- define folder where files are located ----#
$TargetFolder = "C:\test2"
#----- define extension ----#
$Extension = "*.*"
#----- define LastWriteTime parameter based on $Days ---#
$LastWrite = $Now.AddDays(-$Days)

#----- get files based on lastwrite filter and specified folder ---#
$Files = Get-ChildItem $TargetFolder -Include $Extension -Recurse |
         Where  {$_.LastWriteTime -le "$LastWrite"} 

foreach ($File in $Files) {
    if ($File -ne $NULL) {
        Write-Host "Deleting File $File" -ForegroundColor "Red"
        Remove-Item $File.FullName | Out-Null
    } else {
        Write-Host "No more files to delete!" -foregroundcolor "Green"
    }
}

This is a good PowerShell script to delete files older than X number of days, but we would like to delete multiple files saved at different locations with different number of days for each path.

For example, if we have to delete files older than 3 days then we can just add another location like this example:

$TargetFolder = "C:\test","C:\test2" 

and it will take care of both the folders, but we would like to know if there's a way we can have to keep different number of days set for different folders.

In ksh we used to do it this way in config file:

Location 1;//Server1/c$/processed;14
Location 2;//Server2/backup/;3
4

4 Answers

3
votes

Call the script with parameters like "age" and "location"

Param
(
    [int]$days,
    [string]$Targetfolder
)
#----- define parameters -----#
#----- get current date ----#
$Now = Get-Date

#----- define amount of days ----#
#$Days = '3'
#----- define folder where files are located ----#
#$TargetFolder = 'C:\test2'
#----- define extension ----#
$Extension = '*.*'
#----- define LastWriteTime parameter based on $Days ---#
$LastWrite = $Now.AddDays(-$Days)

#----- get files based on lastwrite filter and specified folder ---#
$Files = Get-Childitem $TargetFolder -Include $Extension -Recurse | Where-Object  {$_.LastWriteTime -le "$LastWrite"} 

foreach ($File in $Files) 
{
    if ($File -ne $NULL)
    {
        write-host "Deleting File $File" -ForegroundColor 'Red'
        Remove-Item $File.FullName | out-null
    }
    else
    {
        Write-Host 'No more files to delete!' -foregroundcolor 'Green'
    }
}

Save it as .ps1 and call it like MyScript.ps1 -Targetfolder C:\Blah -Days 4.

1
votes

Here's my solution. You can use this by copying/pasting into a script. Then, call it like this:

PS> $Folders = 'C:\Folder1','C:\Folder2'
PS> .\Remove-OldFiles.ps1 -FolderPath $Folders -DaysOld 30 -WhatIf

Then, if everything looks good, remove the -WhatIf. This should be much faster than the script you had since it uses the newer .where() and .foreach() methods in PSv4.

#Requires -Version 4

[CmdletBinding(SupportsShouldProcess,ConfirmImpact = 'High')]
param (
    [Parameter(Mandatory)]
    [ValidateNotNullOrEmpty()]
    [string[]]$FolderPath,

    [Parameter(Mandatory)]
    [ValidateNotNullOrEmpty()]
    [int]$DaysOld,

    [Parameter()]
    [ValidateNotNullOrEmpty()]
    [ValidateLength(1, 3)]
    [string]$FileExtension
)

$Now = Get-Date

$gciParams = @{
    'Recurse' = $true
    'File' = $true
}

if ($PSBoundParameters.ContainsKey('FileExtension')) {
    $gciParams.Filter = "Extension -eq $FileExtension"
}

$LastWrite = $Now.AddDays(-$DaysOld)

foreach ($path in $FolderPath)
{
    $gciParams.Path = $path
    ((Get-ChildItem @gciParams).Where{ $_.LastWriteTime -le $LastWrite }).foreach{
        if ($PSCmdlet.ShouldProcess($_.FullName, 'Remove'))
        {
            Remove-Item -Path $_.FullName -Force
        }
    }
}
1
votes

I'd recommend parameterizing the script, as @restless1987 suggested. However, if you want to read the information from a file you could create a hashtable in a second PowerShell script:

# config.ps1

$locations = @{
  'C:\processed' = 14
  'D:\backup'    = 3
}

and dot-source that file in your script:

. 'C:\path\to\config.ps1'

so you can use the hashtable like this:

foreach ($TargetFolder in $locations.Keys) {
    $LastWrite = $Now.AddDays(-$locations[$TargetFolder])
    $Files = Get-ChildItem $TargetFolder -Include $Extension -Recurse |
             Where-Object  {$_.LastWriteTime -le $LastWrite} 

    foreach ($File in $Files) {
        ...
    }
}
0
votes

Create a function for your work, and save your paths in a hash table.

$targetFolder = @()

$targetFolder += @{'Folder'='c:\test1'; 'Extension'='*.*'; 'Days'=3}
$targetFolder += @{'Folder'='c:\test2'; 'Extension'='*.*'; 'Days'=5}
$targetFolder += @{'Folder'=@('c:\test3', 'c:\test4'); 'Extension'='*.*'; 'Days'=7}

function DeleteOldFiles($TargetFolder, $Extension, $Days)
{
    $lastWrite = (Get-Date).AddDays(-$Days)

    # do your Get-ChildItem logic here
    $files = Get-Childitem $TargetFolder -Include $Extension -Recurse | Where  {$_.LastWriteTime -le "$lastWrite"} 

    foreach ($file in $files) 
    {
        if ($file -ne $null)
        {
            Write-host "Deleting File $file" -ForegroundColor "Red"
            Remove-Item $file.FullName | out-null
        }
        else
        {
            Write-Host "No more files to delete!" -foregroundcolor "Green"
        }
    }
}

$targetFolder | DeleteOldFiles $_.Folder $_.Extension $_.Days