none
Remove files after X days if the file starts with xxx, xxx

    Question

  • Hello scripting guys.

    I am in the process of changing file retention for a set of backups. the file are named based off of the server, example Dev, Test, Prod

    i want to delete only Dev and test every 7 days and prod after 14 days, but im not sure how to structure the IF statement. i have the code to delete files after x days but dont know how to structure the IF statement. i think it something like;

    $dev = get-childitem D:\backups -recurse

    if ($dev.name = "dev*")

    {

    run retention code

    }

    else

    {"dontrun"}

    something like that

    Thursday, June 28, 2012 6:44 PM

Answers

  • The code works if the file naem contaiss any of teh strings:

    if($file -match 'test|prod'{ 14 }
    elseif($file -match 'dev'{7}
    else { #nothing }

    It should be modified to only test aa teh beginning for those strings so:

    if($file -match '^test|^prod'{ 14 }
    elseif($file -match '^dev'{7}
    else { #nothing }

    Of course each bit returns a number or null so it can be used to drive a pipeline Or just use it:

    if($file -match '^test|^prod'{ if($file.DateCreate - gt 14 days){ delete $file} }
    elseif($file -match '^dev'{ if($file.DateCreate - gt 7days){ delete $file} }
    else { #nothing }


    ¯\_(ツ)_/¯

    • Marked as answer by jeff.k11 Thursday, July 05, 2012 7:06 PM
    Friday, June 29, 2012 2:54 PM
  • Works fine for me.


    PS C:\> 'foo_syntest_bar' -match 'syntest|synprod'
    True
    PS C:\> 'foo_synprod_bar' -match 'syntest|synprod'
    True
    

    Bill

    • Marked as answer by jeff.k11 Thursday, July 05, 2012 7:06 PM
    Thursday, July 05, 2012 6:59 PM

All replies

  • Get-Childitem D:\backups -recurse -filter 'dev*' | Foreach-Object { run retention code (use $_ for current item, not $dev) }

    Thursday, June 28, 2012 6:57 PM
  • So the file name is "Dev" right?  If so then you are in good shape.

    You can also just to this:

    Get-ChildItem -path c:\backups\* -include dev* |
         ?{$_.DateCreated -le ([datetime]::Today).AddDays(-7)}|
         Remove-Item -whatif


    ¯\_(ツ)_/¯

    Thursday, June 28, 2012 7:02 PM
  • Here's my solution:

    $files = Get-ChildItem c:\backups -Recurse
    $date = Get-Date
    foreach ($file in $files) {
        if ($file.name -like 'Prod*') { $ret = -14 }
        else { $ret = -7 }
        if ($file.lastwritetime -lt ($date).AddDays($ret) -and (-not($file.psIsContainer))) { 
            Remove-Item $file.fullname -WhatIf 
            }
        }


    Grant Ward, a.k.a. Bigteddy




    • Proposed as answer by jrv Thursday, June 28, 2012 8:13 PM
    • Edited by Bigteddy Friday, June 29, 2012 5:15 AM
    Thursday, June 28, 2012 7:13 PM
  • I think you are both missing the main point:  The OP wants different cut-off dates for the prod files, but also want to clean up the other files.  14 days for the prod files, and 7 days for the others.

    Grant Ward, a.k.a. Bigteddy


    • Edited by Bigteddy Thursday, June 28, 2012 7:20 PM
    Thursday, June 28, 2012 7:19 PM
  • I think you are both missing the main point:  The OP wants different cut-off dates for the prod files, but also want to clean up the other files.  14 days for the prod files, and 7 days for the others.

    Grant Ward, a.k.a. Bigteddy


    I like yours.  I didn't miss the point.  I just didn't want to write teh whole thing so I showed the method. All that is needed is in my answer.  I do like your interesting way of splitting the two but I doubt if we were given the correct info.

    YOu assume that those are the only files that wil be found.

    Modify it

    if($file -match 'test|prod'{ 14 }
    elseif($file -match 'dev'{7}
    else { #nothing }


    ¯\_(ツ)_/¯


    • Edited by jrv Thursday, June 28, 2012 8:18 PM
    Thursday, June 28, 2012 8:15 PM
  • The files start with dev, test, prod, the whole file is "dev_database_backup_$dateofbackup.rar, so i just need it to find anything with dev,test,prod and do the proper retention.

    I think I have enough to play around with, thanks

    Friday, June 29, 2012 12:48 PM
  • How would i modify it so it will get files like devclientdb_date, testclientws_date.

    the code above works if the files are just test, prod or dev.

    Friday, June 29, 2012 2:47 PM
  • The code works if the file naem contaiss any of teh strings:

    if($file -match 'test|prod'{ 14 }
    elseif($file -match 'dev'{7}
    else { #nothing }

    It should be modified to only test aa teh beginning for those strings so:

    if($file -match '^test|^prod'{ 14 }
    elseif($file -match '^dev'{7}
    else { #nothing }

    Of course each bit returns a number or null so it can be used to drive a pipeline Or just use it:

    if($file -match '^test|^prod'{ if($file.DateCreate - gt 14 days){ delete $file} }
    elseif($file -match '^dev'{ if($file.DateCreate - gt 7days){ delete $file} }
    else { #nothing }


    ¯\_(ツ)_/¯

    • Marked as answer by jeff.k11 Thursday, July 05, 2012 7:06 PM
    Friday, June 29, 2012 2:54 PM
  • { if($file.DateCreate - gt 14 days){ delete $file} }

    this line is getting an unexpected token { in expression error

    Friday, June 29, 2012 4:11 PM
  • { if($file.DateCreate - gt 14 days){ delete $file} }

    this line is getting an unexpected token { in expression error

    That's correct.  You have to write the code.  I just posted the logic tht answered your queston.

    Here is teh time logic in case you are not sure how to use dates.

    $file.CreationTime -lt [datetime]::Today.AddDays(-14)

    The delete $file can be changed to:

    Remove-Item $file -force -whatif


    ¯\_(ツ)_/¯

    Friday, June 29, 2012 4:20 PM
  • $synBackup = get-childitem C:\mypath -recurse
    $date = get-date

    foreach ($file in $synBackup)
    {
    if($file -match '^test|^prod')
    {if($fileCreationTime -lt [datetime]::Today.AddDays(-3))
    { Remove-Item $file -force -whatif }}
    elseif 
    ($file -match '^dev'){ if($file.CreationTime -lt [datetime]::Today.AddDays(-2)){ Remove-Item $file -force -whatif } }
    else { #nothing
     }
    }

    Im getting an error on line 9 at the remove-item. its says it cannot find the path, says it does not exist

    Thursday, July 05, 2012 5:09 PM
  • Hi,

    Please copy and paste the exact error message.

    Bill

    Thursday, July 05, 2012 5:17 PM
  • Try:

    Remove-Item $file.fullname -Force -Whatif


    Grant Ward, a.k.a. Bigteddy

    Thursday, July 05, 2012 5:19 PM
  • If filename contains wildcard-like characters, OP might need -literalpath. Hence the request to copy and paste the exact error message.

    Bill

    Thursday, July 05, 2012 5:22 PM
  • Remove-Item : Cannot find path 'C:\scripts\test_14days.PNG' because it does not exist.
    At C:\scripts\rentention2.ps1:9 char:16
    +         { Remove-Item <<<<  $file -force -whatif }}
        + CategoryInfo          : ObjectNotFound: (C:\scripts\test_14days.PNG:String) [Remove-Item], ItemNotFoundException
        + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.RemoveItemCommand


    Thursday, July 05, 2012 5:23 PM
  • if($file -match '^test|^prod')

     this -match command, will it only find files starting with test or prod? or anything including such as SYNTESTDB, or SYNPRODDB? will it find these files since they include 'test' and 'prod' in the  middle.

    Thursday, July 05, 2012 5:40 PM
  • No. Type the command


    help about_regular_expressions

    at the PowerShell prompt for more information.

    Bill

    Thursday, July 05, 2012 5:47 PM
  • if($file -match '^test|^prod')

     this -match command, will it only find files starting with test or prod? or anything including such as SYNTESTDB, or SYNPRODDB? will it find these files since they include 'test' and 'prod' in the  middle.


    No, it will only match when "test" or "prod" are at the start of the string.  This is because of the caret character ( ^ ), which denotes the start of a line.

    Grant Ward, a.k.a. Bigteddy

    Thursday, July 05, 2012 6:04 PM
  • Ok cool, thanks for that help command. 

    on a side note, where do I find info on "-whatif". i cant really find any good information on it on google.

    if($file -match '^test|^prod')

     this -match command, will it only find files starting with test or prod? or anything including such as SYNTESTDB, or SYNPRODDB? will it find these files since they include 'test' and 'prod' in the  middle.

    So if i put 

    if ($file - match '"syntest|"synprod"')

    it will look for anything matching that string of characters? The actual filename is synprod_database_$date.zip, so i just want synprod upto the underscore. will that command suffice?

    Thursday, July 05, 2012 6:20 PM
  • if ($file - match '"syntest|"synprod"')

    It doesnt seem to like multiple argurments. it works if I just have "syntest" but not both. how do I combine the two arguments?

    Thursday, July 05, 2012 6:26 PM
  • if ($file -match 'syntest|synprod')

    The pipe is an OR in Regex.

    Grant Ward, a.k.a. Bigteddy

    Thursday, July 05, 2012 6:35 PM
  • So do i have 2 arguments in that if statement?

    Thursday, July 05, 2012 6:38 PM
  • I would add that it is very easy to test regular expression matches right at the PowerShell command prompt. Just type a quoted string, the -match operator, the regular expression pattern, and press Enter. PowerShell will output True (if the pattern matched) or False (if it did not match).


    PS C:\> "foobar" -test '^foo'
    True

    Bill

    Thursday, July 05, 2012 6:39 PM
  • They are not really arguments, they are Regex patterns.  Yes, there are 2, because I am separating them with the pipe.  You could include more, each separated by a pipe.

    I recommend Bill's suggestion about reading up on Regular Expressions, as it is a big topic.


    Grant Ward, a.k.a. Bigteddy

    Thursday, July 05, 2012 6:42 PM
  • Ya i can get that with no problem, if I have just if ($file -match "syntest"). It will give me a true.

     but i want to test "syntest" and "synprod" in that one statement but when i removed the ^ and added the " " it doesnt work, gives me a false. 

    Thursday, July 05, 2012 6:43 PM
  • Works fine for me.


    PS C:\> 'foo_syntest_bar' -match 'syntest|synprod'
    True
    PS C:\> 'foo_synprod_bar' -match 'syntest|synprod'
    True
    

    Bill

    • Marked as answer by jeff.k11 Thursday, July 05, 2012 7:06 PM
    Thursday, July 05, 2012 6:59 PM
  • Awesome thanks dude. I was using double quotes not single . 

    Thanks Bill, Grant, Jrv.

    Thursday, July 05, 2012 7:05 PM