Script Dumpster: Keep last X amount of files or Y amount of days

Ever had the need to remove all but the last X amount of copies of a back-up?

And I’m not talking about the copies from the last 2 days, because this can cause issues if the files aren’t created daily [in case of a weekend], in case a back-up has failed in the meantime or if multiple back-up copies have been made in one day.

While at first I was always playing around with the simple solution by checking file age, I ran into a more elegant solution I’d like to share with you.


Both solutions are essentially one liners after the defining of variables, but I’ve split up the code a bit for readability.
Also both codes still have the

switch added, so that you don’t accidentally run this in production and remove the incorrect files.
Please change accordingly!

Keep Y amount of days

This example is used to keep the files from the last 4 days in order to make sure I keep the Friday and Monday file available [no separate back-ups are made over the weekend].
This solution writes the deleted file to a separate log file so you can see which files were [perhaps accidentally] deleted.
Big downsides to this solution are:

  • While I still have the files for Friday and Monday, it means during weekdays I’ll have 4 copies of the back-up file, which can flood your disk.
  • If I make multiple back-ups on 1 day, it will still retain those files, as they simple need to have a maximum age before they’re removed.

Keep X amount of files

Personally this is my preferred and more elegant solution in order to keep only the last X amount of back-up files.

While this can create an issue when you make multiple back-ups on a single day, it’s would be the preferred solution in most cases.


Happy Scripting! 🙂


So you want to edit your input data using PowerShell

In one of my previous blog posts, I had a CSV worth of content in which I wanted to change a specific field of data.

I was racking my brain on how I could best approach this and while working on this, I kept getting a better and cleaner result, but every step approached the issue a bit different, even though the output was as required.


I have a CSV file which contains the following headers

As mentioned in my earlier blog post, I needed to make sure that my PurchaseDate was in a specific format, so it would be processed correctly by Excel.

I wanted to get an Excel file which had all the above data and either a new column with the correct date format or have PurchaseDate values overridden by the proper value.

Ideally I would have an extra column which would calculate the actual age of the machine, by comparing the PurchaseDate to Today, but I already know a nice way to do this in Excel, so that’s just to play around with.

The basics

Ok, first things first, let’s get some data and declare some variables:

Simple right?

I want to output the details to NewList.csv , so I need to keep that in mind.
Every try will eventually get the following added to the end of it


First try

I had thought to use all data from my first array of objects $Computers and put all the relevant data in to a new object.

I start off by creating a blank array called $warranties, which I will later fill up with all required data.

Then I create a new PSObject for each machine in my list called $warranty, which I add to the $warranties array using the +=  assignment operator .
It’s rather clunky,  but hey, it gets the job done!

Second shot

But wait, why don’t I just add a new column to my current array and just use that column instead?

Wow, that looks a lot cleaner and I don’t even need to define all the previous columns.
While in my case this is preferred, there are circumstances when you have TOO much data in your original CSV file and in that case using the First Take solution can be used to clean up the data.

Third time’s a charm

I’m on the right track  now, making my script cleaner, easier and still functional.
Just one small tweak should do it:

Again using the Add-Member Cmdlet to add a property to my $computer object, but this time I give it the Name of an already existing property, using the -Force parameter to override the current value.


Bonus points up ahead!

As mentioned before, ideally I would also like to have a column added which displays the current age of a machine.
In order to do this you need to simply compare today’s date to the PurchaseDate.

Here I calculate the amount of ticks between Now and PurchaseDate which gives me my age.
For some strange reason it increments all values by 1 though, which means that when using this value, you need to subtract 1.

Don’t believe me, give it a shot, but this gives me the information required.

Last but not least, perhaps some people would like to know the formula for in Excel, in case they prefer this:

Happy Scripting! 🙂


Going on a Get-Date…part 2

As mentioned previously in my first part of this Get-Date series, I had run into some issues that were seemingly easy to resolve, yet proved to be a bit more hassle than expected.

Funny enough, the second issue where I ran into date issues was just a day or so apart from the first, so I thought I’d resolve my issues with the knowledge I had obtained previously.

The Problem

I had received an Excel sheet which contained various information, one column being Warranty dates.
Now the issue was that the Excel sheet was generated on a system which had NL-NL Culture configuration, while my machine is running on EN-US configuration.

The reason this is important is because NL-NL has dates sorted as follows:

while EN-US has this configuration:

which means Excel doesn’t recognize the input as dates and formats the cell as general or in some cases even as text.

Take for example 02/07/2012.
NL-NL would say this is 2 July 2012, while EN-US says this is 7 February 2012.

But in the case of for example 24/11/2010 NL-NL would say 24 November 2010 and EN-US would just flip, because that simply can’t be a date format.

The Struggle

When trying to manipulate the data through PowerShell I was running into issues..

Ok, so I needed to convert this to a DateTime object.. let’s give this a shot!

Ah, crap, that was not what I needed…

Let’s use the tips give on my previous issue

Ok, this was not the way to go.. I need to specify which format my date will be in, so that it can be parsed correctly.

So close, yet so far away…

Using my best friend in situations like this, I tracked down the following site which gave excellent examples on how to resolve issues like this.
I first had to define the template format I was using and then parse my input using said template.

Grrrrr, this is becoming annoying!

Browsing more information on the .NET DateTime Parse and ParseExact Methods provided me with some insight on how it should work, but still I was getting the same error message as before.

It was time to call for help… it had to be something simple, but I was not getting the outcome as expected.

The Solution

How simple can it be… 🙁

Again the major issue here is PROPERLY reading what is required.. the answer was right in front of me

Help again came through the FaceBook PowerShell group, and in this case by my local DuPSUG founder and PowerShell MVP Jeff Wouters :

The template format I had defined earlier was incorrect!

Should be:

Besides that, while the earlier site had mentioned using $null as format provider, but best is to define this properly:

Technical info on [System.Globalization.CultureInfo]::InvariantCulture can be found here, but the best short and readable description I could find was:

The CultureInfo.InvariantCulture property is used if you are formatting or parsing a string that should be parseable by a piece of software independent of the user’s local settings.

Now I can simply display the dates in the correct format and now I see that Excel correctly sees the input as Dates and I can finally sort as wanted!


Happy Scripting! 🙂