File Age Groupings with PowerShell

I’m always talking about how much the object-nature of PowerShell makes all the difference in the world. Today, I have another example. Let’s say you want to analyze a directory, perhaps a shared group folder for a department. And you want to identify files that haven’t been modified in a while. I like this topic because it is real world and offers a good framework for demonstrating PowerShell techniques.

You would like to divide the files into aging “buckets”. Let’s begin by getting all of the files. I’m using PowerShell 3.0 so you’ll have to adjust parameters if you are using 2.0. You can run all of this interactively in the console, but I think you’ll find using a script much easier.

Now, let’s add a new property, or member, to the file object called FileAgeDays which will be the value of the number of days since the file was last modified, based on the LastWriteTime property. We’ll use the Add-Member cmdlet to define this property.

The new property is technically a ScriptProperty so that we can run a scriptblock to define the value. In this case we’re subtracting the LastwriteTime value of the each object from the current date and time. This will return a TimeStamp object but all we need is the TotalDays property which is cast as an integer, effectively rounding the value. In a pipelined expression like Select-Object you would use $_ to indicate the current object in the pipeline. Here, we can use $this.

Next, we’ll add another script property to define our “bucket” property.

The script block can be as long as you need it to be. Here, we’re using an If/ElseIf construct based on the FileAgeDays property we just created. If we look at $files now, we won’t see these new properties.

fileage-01

But that is because the new properties aren’t part of the default display settings. So we need to specify them.

fileage-02

Now, we can group the objects based on these new properties.

fileage-03Or perhaps we’d like to drill down a bit more.

Now we’ve added a new member to the GroupInfo object that will show the total size of all files in each group by MB. Don’t forget to use -Passthru to force PowerShell to write the new object back to the pipeline so it can be saved in the grouped variable. Finally, the result:

fileage-04

And there you go. Because we’re working with objects, adding new information is really quite easy. Certainly much easier than trying to do something like this in VBScript! And even if you don’t need this specific solution, I hope that you picked up a technique or two.

PowerShell Pivot Tables

I was working on a question in the Ask Don and Jeff forum about multidimensional arrays. The ultimate goal of sorts was to create an HTML report that contained in essence a pivot table. This device allows you to slice and dice data so that you can identify trends or patterns. In PowerShell, there aren’t too many tools that allow you to “re-organize” an object. For example, say you have a variable that contains the results of querying a few computers for some critical services. But you want a table that shows you the computername as the Y-Axis and each service name as the header on the X axis. For each computer, the intersection should be the status of said property. In other words, a result like this:

At a glance I can see where there might be problems. Blanks indicate the service doesn’t exist on that computer. In this case, you might be able to get similar results with some grouping and Format-Table tricks. But more than likely you wouldn’t have something you could export to XML or convert to HTML.
Or say you have a directory listing for a handful of file extensions and you want to see a count of each extension for each folder, perhaps something like this:

That last row is not a sum, but rather the count of each of those file types in the root of C:\Scripts. I did all of this with a function I call New-PSPivotTable.

There is a lot going on here but I’ve tried to use comments and Write-Verbose statements to make it easier to track. In short, the function takes a collection of data and builds a table based on the property names and values you specify. You can build a table on a property like I did with the services. You can create a table based on count or on size. For the latter you need to also specify what property name to measure to calculate the size.

The function is writing an object to the pipeline which means you can transform the output however you need it.

Honestly, I think the best thing is for you to download New-PSPivotTable and try it out. The download has full help and examples which you should read. I really hope you find it useful and if you run into some scenarios where this doesn’t work the way you think it should, please let me know.

Friday Fun Drive Usage Console Graph

I think you’ll like this. Normally, I prefer my PowerShell commands to write objects to the pipeline. But there’s nothing wrong with sending output directly to the console, as long as you know that the output is intended only for the screen. What I find frustrating is the use of Write-Host when really, pipelined objects would be better. But for today, I’m going to revel in the beauty of the console and create a colorized drive utilization graph. Continue reading