Server Fault is a question and answer site for system and network administrators. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I would like to create a maintenance script that would run on each of our servers to clean out common drop/archive directories. Preferably the script would use a reference file for the folder path and desired aging limit. Then the script would clean that path of files older than the aging limit. The input reference file would look something like this:

c:\logs\iis\siteA\ 30
c:\logs\job1\ 60
e:\archive\clientA\ 90

The first component is the file path; and the second is the number of days files should be retained, separated by a space.

Now for the script I have the following; however, I am embarrassingly deficient in scripting experience. (i am more networking oriented)

#Attempted loop
Foreach ($ParentDir = Get-Content .\paths.txt $arg1, $arg2)
{$limit = (Get-Date).AddDays(-$arg2)
$path = $ParentDir

# Delete files older than the $limit.
Get-ChildItem -Path $path -Recurse -Force | Where-Object { !$_.PSIsContainer -and $_.CreationTime -lt $limit } | Remove-Item -Force}

I feel like the logic is close but my syntax is off. Is my approach doable? is there a better way? Could you help with the syntax? Using poweshell v3.

Credit where credit is due lots of the logic i took from deadlydog from this post.

share|improve this question
To elaborate, my intention is to schedule this single script to run once daily. Ideally I would only have one task for all the directories I want cleaned. Therefore being able to specify the reference file for the paths and variable retention age is really important. To add a new path I just edit the reference file rather than creating a new task. – MaCuban Feb 19 '14 at 23:04

Edited to include your requested text file of

c:\logs\iis\siteA\ -30
c:\logs\job1\ -60
e:\archive\clientA\ -90

I tested the new bits of code separately from what I had lying around, but it should still do what you want, I think.

$controlfile = "c:\path\to\yourfile.txt"    
$curr_date = Get-Date

New-Item -ItemType directory -Path f:\delete

foreach ($line in get-content $controlfile)
    $split = $line.split(" ")
    $file_path = $split[0]
    $max_days = $split[1]

    $del_date = $curr_date.AddDays($max_days)

    # move the files to the kill directory
    Get-ChildItem $file_path | Where-Object { $_.LastWriteTime -lt $del_date } |  Move-Item -destination "f:\delete"

The reason it moves it to a different directory is because there's apparently a bug in recursive deletes, and my data is many, many subdirectories deep, so once I've got everything moved to the kill directory, I run this:

del /f/s/q f:\delete > nul
rmdir /s/q f:\delete

If you don't have that problem, you could instead add this to the end of the above bit of PowerShell:

$del_dir = "f:\delete"
$fso = New-Object -ComObject scripting.filesystemobject
share|improve this answer
This is very helpful and thanks for the notice on the recursive bug. For me it is really important that the script is scheduled and allow for variable retention on different directories... I would like to avoid creating a task/script for each directory. this will be really helpful in the short term though. – MaCuban Feb 19 '14 at 23:08
Now that I've had a chance to look at it, I've edited it to add your control file. I hope that helps. – Katherine Villyard Feb 20 '14 at 3:39

You can create a cmdlet for this, so you can also use it in your command line:



ls $folder | % { if ($_.LastWriteTime -le (date).AddDays(-$expiry)) { rm $_ -fo } }


.\script.ps1 -folder "c:\logs\iis\siteA\"  -expiry 30
.\script.ps1 -folder "c:\logs\job1\"       -expiry 60
.\script.ps1 -folder "e:\archive\clientA\" -expiry 90
share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.