Directory Diving
In this issue:
I expect that for many of you PowerShell is an easy to use tool because it isn't difficult to find and run a cmdlet to achieve a particular goal. Cmdlets are typically well documented and have a set of parameters to fine-tune the command's behavior. Cmdlets and functions abstract a lot of the .NET Framework so that you can use PowerShell without having to be a .NET developer.
However, as you gain experience, you'll encounter situations where you need to forego the cmdlet and dive into the deep end of .NET. You don't always have to rely on a cmdlet or function. Should the need arise, you can create code that utilizes the underlying .NET voodoo. This allows you to have more granular control of an operation. I want to dive into some of that today with the file system.
Normally, we can use Get-ChildItem.
PS C:\> Get-ChildItem c:\scripts -Directory | Measure | Select count
Count
-----
189
Easy to use, and the cmdlet offers several parameters to control how the command runs. But there is always overhead with a cmdlet; a trade-off for ease of use. If we are willing to do the work, we can eke out a little more performance. This will be more noticeable with larger directories.
DirectoryInfo Methods
When I run Get-ChildItem on a location, I am implicitly creating aSystem.IO.DirectoryInfo` object. This class offers a few methods that we can take advantage of.
PS C:\> $folder = Get-Item C:\Scripts
PS C:\> Get-TypeMember $folder.GetType().Fullname -MemberType method | Where {$_.name -match "(Directories)|(file)"}
Type: System.IO.DirectoryInfo
Name MemberType ResultType IsStatic IsEnum
---- ---------- ---------- -------- ------
EnumerateDirectories Method IEnumerable`1
EnumerateFiles Method IEnumerable`1
EnumerateFileSystemInfos Method IEnumerable`1
GetDirectories Method DirectoryInfo[]
GetFiles Method FileInfo[]
GetFileSystemInfos Method FileSystemInfo[]
> You will see different results when using Windows PowerShell.
Today I want to focus on the directory-related methods.
GetDirectories()
The GetDirectories() method will give you results identical to running Get-ChildItem -directory. The method has several overloaded definitions you can use.
PS C:\> $folder.GetDirectories.OverloadDefinitions
System.IO.DirectoryInfo[] GetDirectories()
System.IO.DirectoryInfo[] GetDirectories(string searchPattern)
System.IO.DirectoryInfo[] GetDirectories(string searchPattern, System.IO.SearchOption searchOption)
System.IO.DirectoryInfo[] GetDirectories(string searchPattern, System.IO.EnumerationOptions enumerationOptions
The basic syntax will get all top-level directories
PS C:\> $folder.GetDirectories() | Measure | Select Count
Count
-----
189
```
<h3 id="searchpattern">SearchPattern</h3>
You can limit your search to specific directories with a search pattern string. This parameter will accept wildcards.
```powershell
PS C:\> $folder.GetDirectories("psworkitem")
Mode LastWriteTime Length Name
---- ------------- ------ ----
l---- 3/16/2026 12:28 PM PSWorkItem
PS C:\> $folder.GetDirectories("*work*")
Mode LastWriteTime Length Name
---- ------------- ------ ----
l---- 3/16/2026 12:28 PM PSWorkItem
l---- 4/10/2026 8:15 PM putting-powershell-work
l---- 10/7/2025 8:40 AM Workflow
A simple wildcard search is the best you can do to filter results.
SearchOptions
The basic method is to get top-level directories. But another syntax option uses a search option. As you can see in the syntax this is System.IO.SearchOption object. I find it easiest to use my Get-TypeMember command.
PS C:\> Get-TypeMember System.IO.SearchOption
Type: System.IO.SearchOption
Name MemberType ResultType IsStatic IsEnum
---- ---------- ---------- -------- ------
AllDirectories Field System.IO.SearchOption True
TopDirectoryOnly Field System.IO.SearchOption True
GetType Method Type
HasFlag Method Boolean
ToString Method String
This looks simple enough. I can explicitly search for top-level directories only.
PS C:\> $folder.GetDirectories("*work*","TopDirectoryOnly")
Mode LastWriteTime Length Name
---- ------------- ------ ----
l---- 3/16/2026 12:28 PM PSWorkItem
l---- 4/10/2026 8:15 PM putting-powershell-work
l---- 10/7/2025 8:40 AM Workflow
Or search the entire tree.
PS C:\> $folder.GetDirectories("*work*","AllDirectories") | Select fullname
FullName
--------
C:\Scripts\PSWorkItem
C:\Scripts\putting-powershell-work
C:\Scripts\Workflow
C:\Scripts\Workflow\Workflow Samples - CTP1
C:\Scripts\Workflow\Workflow Samples - Deep Dive
C:\Scripts\GitDevTest\.github\workflows
C:\Scripts\jdhitsolutions\.github\workflows
C:\Scripts\PSGalleryReport\.github\workflows
C:\Scripts\tips\.github\workflows
You will need to supply a search pattern, when using a search option. Make your default the wildcard.
PS C:\> $folder.GetDirectories("*","AllDirectories") | Measure | Select count
Count
-----
5985
By the way, this took 570ms.
Using Get-ChildItem yields slightly different results in about 580ms.
PS C:\> dir c:\scripts -Directory -Recurse | Measure | select Count
Count
-----
1313
The GetDirectories() method will also get hidden and system folders. You can control this behavior with the third syntax option.
EnumerationOptions
The last syntax uses an EnumerationOptions object.
PS C:\> Get-TypeMember System.IO.EnumerationOptions
Type: System.IO.EnumerationOptions
Name MemberType ResultType IsStatic IsEnum
---- ---------- ---------- -------- ------
GetType Method Type
AttributesToSkip Property FileAttributes True
BufferSize Property Int32
IgnoreInaccessible Property Boolean
MatchCasing Property MatchCasing True
MatchType Property MatchType True
MaxRecursionDepth Property Int32
RecurseSubdirectories Property Boolean
ReturnSpecialDirectories Property Boolean