Measuring Folders with PowerShell One More Time

I know I just posted an update to my Measure-Folder function but I couldn’t help myself and now I have an update to the update. Part of the update came as the result of a comment asking about formatting results to a certain number of decimal places. I typically the Round() method from the Math .NET class.

So I added a parameter, Round, to automatically round to a certain number of decimal points. The default is 2 but you can enter any value between 0 and 10. If you use 0 the effect is to treat the value as an integer.

The other change I made was to simplify the code. My intention when creating a PowerShell tool is not have duplicate commands, or commands that are very, very similar. In last week’s version I used a Switch statement to dynamically create properties and values. But each item was practically the same except for the unit of measurement. So instead I came up with a hash table of units.

With this I can use the hashtable key as the part of property name, and the value for formatting the result.

The property name is created on the fly for anything other than the default “bytes”.

I use the same process if the user wants the average. Here’s the complete revised function.

The results are the same, with the addition of the rounding option.

I swear this is the last change. Unless someone gives me a cool idea! Enjoy.

Measure that Folder with PowerShell Revisited

Last year I posted a PowerShell function to measure the size of a folder. I recently had a need to use it again, and realized it needed a few tweaks. By default, the original version recursively searched through all subfolders. But there may be situations where you only want to measure the top level folder, so I added a –NoRecurse parameter. I also added a parameter to display an average value as well.


Figure 1 Measuring the Temp folder in GB


Figure 2 Measuring my Documents folder including average size in KB

Here is the updated function:

I hope you’ll let me know what you think or what additional features would be helpful.

Update: For an even newer version of this function go here.

There’s Sum-thing Happening Here

calculatorI am one of those IT Pros who keeps close tabs on system resources. I like to know what is being used and by what. As you might imagine, a cmdlet like Get-Process, is pretty useful to me. One of the things I’m always checking is how much memory Google Chrome is taking. I don’t mean to pick on Chrome as I derive great benefit from it. But because I keep it open for days at a time I think system resources get a little carried away. So every once in a while I like to see how many Chrome processes are running and how much they are using.

Now, what I really want is a total. I can get that for a single property easy enough using Measure-Object.

But ideally I’d like to get totals for all of the properties I see with Get-Process. So I wrote an advanced PowerShell function called Get-ProcessTotal.

The main part of the function gets all instances of a process and then creates a custom object with a sum total for several properties.

The output also includes the computer name, in case you are querying a remote computer, the total count and also the original process objects in case you need to do something else with them.

That could be sufficient, but all the values would be in bytes and the default display would be a list. Instead I wanted default output like I get with Get-Process. So I took advantage of PowerShell’s extensible type system and created my own format data xml file. Actually what I did was to find the section in the DotNetTypes.format.ps1xml file for process objects, copied it and tweaked it.

My original idea was to have a separate XML file. If I was building a module, that would be the best choice. But this was a single, stand-alone function so I added some logic to create the XML file on first use and add it to my PowerShell session. The XML content is stored as a Here string in the function.

In short, the function first tests to see if there is format data for an object of type My.ProcessTotal. If not, in then tests for the XML file which I’m storing in the WindowsPowerShell folder. If it doesn’t exist, the file is created. In any event once the file exists it is then loaded into PowerShell using Update-FormatData.

How does PowerShell know what type to use? I told it. When I defined my custom object I also gave it a new type name.

Once the function is loaded into my session I can now get a result like this:

The output is just like Get-Process except the values are sums. I also added an option to get an average instead just in case. If you pipe to Get-Member you’ll see the new type definition, as well as the other non-default properties.

There are some other examples in the comment based help. The script also creates an alias so if you don’t want it be sure to comment out the line at the end.

I hope some of you will kick it around and let me know what you think. Or at the very least I hope you picked up a new technique or idea.

Friday Fun: The Measure of a Folder

rulerLast week, I demonstrated how to measure a file with PowerShell. This week let’s go a step further and measure a folder. I’m going to continue to use Measure-Object although this time I will need to use it to measure numeric property values.

Here’s the complete function after which I’ll point out a few key points.

The command will use the current path or you can pipe in a directory name, or the output of a Get-ChildItem expression as I show in the help examples. One thing I added is that I test the path to make sure it is a file system path because anything else wouldn’t really work.

I resolve the path so that I can get the actual name of the current location (.) and then test the provider. The other interesting feature of this function is that I format the results on the fly.

The function has a Unit parameter which has a default value of bytes. But you can also specify one of the PowerShell numeric shortcuts like KB or GB. In the function I use a Switch construct to create a custom property on the fly.

Because there can only be a single value for $Unit, I’m including the Break directive so that PowerShell won’t try to process any other potential matches in the Switch construct. Realistically, there’s a negligible performance gain in this situation but I wanted you to see how this works.

measure-folder

I’ve taken some basic commands you could use interactively such as Get-ChildItem and Measure-Object and built a tool around them using a hashtable of properties to create a custom object. I hope you pick up a tip or two from this. If you have any questions about what I’m doing or why, please don’t hesitate to ask because someone else might have the same question.

Enjoy your weekend!

Friday Fun: The Measure of a File

ruler I’ve been working with PowerShell since the days of Monad and have written a lot of PowerShell scripts. Out of idle curiosity, and the need for a Friday Fun topic, I decided to see how many lines of PowerShell I have written. Or at least that are in my Scripts folder. Turns out I have 2003 ps1 files for a total of 143,375 lines of PowerShell. There’s a bit of a fudge factor here has I often break single and long PowerShell expressions into multiple lines. So the number is an approximation. Here’s how I figured this out.

The Measure-Object cmdlet can also be used to measure text files. You can get values like total number of words, characters and lines. All you need to do is pipe content to the cmdlet.

So to measure, let’s say all of the script files I’ve created this year I can run a command like this:

I included the parameter to skip blank lines. But I wanted a bit more information such as the total number of files and perhaps an average so I came up with this code.

When you use Measure-Object with the text parameters, you don’t get a count property like you normally would. So I’m using one of the common parameters, OutVariable, which has an alias of OV, with Get-Childitem (the dir command). When using Out-Variable, the results are written to the pipeline and to the variable. This means I can use this variable later in my expression to create custom properties for the TotalFiles and Average.

Let’s say I want the same results for all files created this year. I’ll need to move my capture variable later in the expression:

I need to make sure my count and averages are based on the filtered results.

Or I can include unfiltered results as well.

I’ve added OutVariable to the first part of my expression. I also went ahead and used more meaningful variable names. Since I had the data, I decided to add a bit more data. Finally, even though I’ve primarily been using the count value for the variables, they hold full objects which leads to some intriguing possibilities:

So today’s fun really covered two topics, using Measure-Object with text files and the OutVariable common parameter. Enjoy!