Faster FileInfo
In this issue:
- GetFiles()
- EnumerateFiles()
- GetFileSystemInfos()
- EnumerateFileSystemInfos()
- Get-IOFolderSize
- Summary
Last time I demonstrated a few .NET techniques for listing directories and sub-directories from a given folder. You might want to use these idea for your own scripting projects where you want a little more granular control over the process or want to eke out a little more performance. We can do a similar thing with files.
I'm sure you've run a command like this.
$a = dir c:\scripts -file
This took 221ms to get 4500 files. Let's look at an alternative.
GetFiles()
As before, we need a reference to the parent folder.
$folder = Get-Item C:\Scripts
Now we can use the GetFiles() method, which has similar overload definitions as GetDirectories().
PS C:\> $folder.GetFiles.OverloadDefinitions
System.IO.FileInfo[] GetFiles()
System.IO.FileInfo[] GetFiles(string searchPattern)
System.IO.FileInfo[] GetFiles(string searchPattern, System.IO.SearchOption searchOption)
System.IO.FileInfo[] GetFiles(string searchPattern, System.IO.EnumerationOptions enumerationOptions)
Getting files in the root directory only now only takes 65ms.
$b = $folder.GetFiles()
The contents of $a and $b are identical.
And as with directories, I can search on a pattern.
PS C:\> $folder.GetFiles("*.zip") | Measure-Object length -sum | Select-Object count,sum
Count Sum
----- ---
20 283687.00
I can use a search option.
PS C:\> $folder.GetFiles("*.zip","AllDirectories") | Measure-Object length -sum | Select-Object count,sum
Count Sum
----- ---
40 7852173.00
This took about 3 seconds compared to dir c:\scripts\*.zip -Recurse | measure length -sum | select count,sum which took over 31 seconds to complete!
Hmmm...I wonder how many files it had to process.
PS C:\> $all = $folder.GetFiles("*","AllDirectories")
PS C:\> $all.count
18310
Or I can get very granular with enumeration options.
PS C:\> $opt = [System.IO.EnumerationOptions]::new()
PS C:\> $opt.RecurseSubdirectories = $True
PS C:\> $opt.attributesToSkip+="SparseFile"
PS C:\> $opt.MaxRecursionDepth = 1
PS C:\> $opt
RecurseSubdirectories : True
IgnoreInaccessible : True
BufferSize : 0
AttributesToSkip : Hidden, System, SparseFile
MatchType : Simple
MatchCasing : PlatformDefault
MaxRecursionDepth : 1
ReturnSpecialDirectories : False
Now to use it.
PS C:\> $c = $folder.GetFiles("*",$opt)
PS C:\> $c.count
6487