Today I wanted to find out the average size of a group of files. To make it more challenging, I wanted to find the average size of a group of files that existed co-mingled in a directory with several other files I didn't care about. PowerShell to the rescue!
In my examples, we'll say I wanted to average the size of all .CSV files in the C:\temp directory. I define the $target variable to contain a string that defines which files you want to work with. There's no magic here; it's the same string I'd type on a command line, but you can do much more complicated expressions using wildcards and such. Here's how I defined it:
$target = "c:\temp\*.csv"
Here's the script I came up with:
$myfile = $(dir $target | select-object Name,Length)
for ($($myfilesize = 0; $i=0); $i -lt $myfile.count; $i++) {$myfilesize += $myfile[$i].Length}
$myfileavg = "{0:N2}" -f $($myfilesize / $myfile.count / 1024)
Write-Output ("Average size of selected files: " + $myfileavg + "KB")
Here's how the script works.
- The script performs the dir command against the target (really an alias to Get-ChildItem cmdlet)and pipes the output through the Select-Object cmdlet so we can specify which attributes we care about -- in this case only Name and Length. It then stores the results in the $myfile variable.
- Now we can use a for loop to iterate through all the elements of the $myfile and add up the total number of bytes.
- Simple arithmetic -- total number of bytes divided by the number of files (which is the Count property of the $myfile variable) -- gives us our answer in bytes. We divide it by 1,024 to convert to kilobytes, and use the .NET string formatting functions (the {0:N2} bit) to tell PowerShell to round the result to two decimal places.
- We then print the output out. Done!
I'm sure there are easier and cleaner ways to do this under PowerShell, but my point is to show how a task that would take a lot more work under VBScript or conventional Windows command-line scripting can be done quickly in PowerShell.
Extra credit: say you just wanted to import the files and sizes into Excel? This one-liner creates the CSV file:
dir $target | Select-Object Name,Length | export-csv csv.csv -NoTypeInformation
Note that you need to use Select-Object here to preserve the object information of the original objects you collected. If you use Format-Table as I first did, it won't work; your CSV file will contain the object information of the output lines of the table, not the objects used to create the table. The -NoTypeInformation suppresses the inclusion of the #TYPE header, an additional line that documents what object type Export-CSV detected.