Monday, March 29, 2010

powershell: delete files older than X

It really is that easy.

Get-ChildItem $env:temp/myfiles | where {$_.Lastwritetime -lt (date).addminutes(-15)} | remove-item

Everybody has needed the 'delete files older than X' script.  One more thing that is easier in powershell.  In this case I have $env:temp/myfiles as my directory containing the files.  I could also add -recurse to get-childitem if I wanted to get subdirectories as well.  Anonymous noted below that you can add a test to exclude directories if you just want to clean the files out of the directory structure.  I am using addminutes to delete files older than now - 15 minutes but you have other options.  More on that here.

Note that if we want to delete all files older than X we would use -lt.  ie, the timestamp of the file is older than 15 minutes ago.  If we want to delete files newer than X we would use -gt.  ie, the timestamp of the file is newer than 15 minutes ago.  X, in our case, is the time now minus 15 minutes.

 We are going to 'at' it.  Although the Vista and later scheduling engine is vastly improved and renamed to schtasks.

We are going to run this every 15 minutes.
schtasks /create /ru "NT Authority\NETWORK SERVICE" /F /sc daily /mo 1 /ri 15  /st 00:00 /du 0023:50 /tr "powershell -command {
Get-ChildItem $env:temp/myfiles | where {`$_.Lastwritetime -lt (date).addminutes(-15)} | remove-item -recurse"  /TN "File Delete"}


Updated: 20110310 - fixed some issues w/ the schtask line (notice the `) and added a note about the pscontainers test noted by anonymous below.

11 comments:

  1. You can also do it with forfiles utility which is part of resource kit.
    http://techibee.com/tips/how-to-delete-files-older-than-certain-days/231

    ReplyDelete
  2. Sitaram: Thanks for the note. while there are a few applications that can do this, powershell is already installed on any new server we are building (2k8r2). I like to try to avoid extra installs as much as possible so I can have generic solutions across my servers. Of course, I probably should have just done it in vbs (again). B)

    It was so easy when I went to do it in powershell I just had to put it up.

    ReplyDelete
  3. Yes, agree. But I wamt to help peopel who didn't see the beauty of powershell yet :-)

    ReplyDelete
  4. I just have a question here.. Is this script giving any errors/opo-ups on console? I am asking because it will fail to delete in use file and just wondering what it is doing in such case.

    ReplyDelete
  5. This comment has been removed by the author.

    ReplyDelete
  6. hmmm... good point. we are just cleaning out very temporary cache files so we don't expect to have open files. that said, it would be a good idea to hash this out with some error handling. Something like
    try {
    Get-ChildItem $env:temp/myfiles | where {$_.Lastwritetime -lt (date).addminutes(-15) | remove-item}
    catch {
    $failed = $true
    }
    if ($failed) {
    (new-object Net.Mail.SmtpClient("127.0.0.1")).send("From@from.com","TO@EMAIL.COM","Help", "Job Failed")
    }

    plus add logging. B)

    ReplyDelete
  7. Hello,

    ok please keep in mind that you normaly need to set some filters like only .tmp files or something. Another point is, normaly you delete files older than 2 weeks, 2 month and so on. if you give minutes for that thats very uncool

    regards
    memeyselfandi

    ReplyDelete
  8. memyselfandi,
    depending on your requirements you can filter this with either -filter or simply starting with
    get-childitem e:\directory\*.bak
    or similar. Also, do remember that the addminutes can be replaced w/ adddays, addticks, addyears, etc as you require. Or, if that is also uncool, just add more minutes to equal the time you need. There are 525600 minutes in a year, in case calculators are uncool as well.

    follow this link from the original article: http://msdn.microsoft.com/en-us/library/system.datetime_members.aspx for more details on how to use the .net date object and methods.

    ReplyDelete
  9. cornasdf: Thank you for the great info. I tried running this bit of code, but I get the following error:

    Method invocation failed because [System.String] doesn't contain a method named 'addDays'.
    At line:1 char:74
    + Get-ChildItem $LOG_DIR\*.log | where {$_.Lastwritetime -lt (date).addDays <<<< (-7)} | remove-item
    + CategoryInfo : InvalidOperation: (addDays:String) [], RuntimeException
    + FullyQualifiedErrorId : MethodNotFound


    Here is my statement:
    Get-ChildItem $LOG_DIR\*.log | where {$_.Lastwritetime -lt (date).addDays(-7)} | remove-item


    Any ideas on what would be causing this? I always thought this was caused when trying to perform certain methods on strings, but "date" should not return a string.

    Thanks.

    ReplyDelete
  10. Matthew, I didn't see this post until now. I ran your snippet (at least the date part) and it seems fine. what happens when you run
    (date).addDays(-7)

    ReplyDelete
  11. I also wanted to recurse subfolders so have modified as follows. The !$_.PSIsContainer test stops folders from being removed.

    Get-ChildItem -recurse| where {!$_.PSIsContainer -and $_.Lastwritetime -lt (date).adddays(-14)}|remove-item

    ReplyDelete

analytics