How do I get only directories using Get-ChildItem?

PowershellPowershell 2.0

Powershell Problem Overview


I'm using PowerShell 2.0 and I want to pipe out all the subdirectories of a certain path. The following command outputs all files and directories, but I can't figure out how to filter out the files.

Get-ChildItem c:\mypath -Recurse

I've tried using $_.Attributes to get the attributes but then I don't know how to construct a literal instance of System.IO.FileAttributes to compare it to. In cmd.exe it would be

dir /b /ad /s

Powershell Solutions


Solution 1 - Powershell

For PowerShell 3.0 and greater:

Get-ChildItem -Directory

You can also use the aliases dir, ls, and gci


For PowerShell versions less than 3.0:

The FileInfo object returned by Get-ChildItem has a "base" property, PSIsContainer. You want to select only those items.

Get-ChildItem -Recurse | ?{ $_.PSIsContainer }

If you want the raw string names of the directories, you can do

Get-ChildItem -Recurse | ?{ $_.PSIsContainer } | Select-Object FullName

Solution 2 - Powershell

In PowerShell 3.0, it is simpler:

Get-ChildItem -Directory #List only directories
Get-ChildItem -File #List only files

Solution 3 - Powershell

Use

Get-ChildItem -dir #lists only directories
Get-ChildItem -file #lists only files

If you prefer aliases, use

ls -dir #lists only directories
ls -file #lists only files

or

dir -dir #lists only directories
dir -file #lists only files

To recurse subdirectories as well, add -r option.

ls -dir -r #lists only directories recursively
ls -file -r #lists only files recursively 

Tested on PowerShell 4.0, PowerShell 5.0 (Windows 10), PowerShell Core 6.0 (Windows 10, Mac, and Linux), and PowerShell 7.0 (Windows 10, Mac, and Linux).

Note: On PowerShell Core, symlinks are not followed when you specify the -r switch. To follow symlinks, specify the -FollowSymlink switch with -r.

Note 2: PowerShell is now cross-platform, since version 6.0. The cross-platform version was originally called PowerShell Core, but the the word "Core" has been dropped since PowerShell 7.0+.

Get-ChildItem documentation: https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.management/get-childitem

Solution 4 - Powershell

A cleaner approach:

Get-ChildItem "<name_of_directory>" | where {$_.Attributes -match'Directory'}

I wonder if PowerShell 3.0 has a switch that only returns directories; it seems like a logical thing to add.

Solution 5 - Powershell

Use:

dir -r | where { $_ -is [System.IO.DirectoryInfo] }

Solution 6 - Powershell

From PowerShell v2 and newer (k represents the folder you are beginning your search at):

Get-ChildItem $Path -attributes D -Recurse

If you just want folder names only, and nothing else, use this:

Get-ChildItem $Path -Name -attributes D -Recurse

If you are looking for a specific folder, you could use the following. In this case, I am looking for a folder called myFolder:

Get-ChildItem $Path -attributes D -Recurse -include "myFolder"

Solution 7 - Powershell

Less text is required with this approach:

ls -r | ? {$_.mode -match "d"}

Solution 8 - Powershell

Use:

dir -Directory -Recurse | Select FullName

This will give you an output of the root structure with the folder name for directories only.

Solution 9 - Powershell

The accepted answer mentions

Get-ChildItem -Recurse | ?{ $_.PSIsContainer } | Select-Object FullName

to get a "raw string". But in fact objects of type Selected.System.IO.DirectoryInfo will be returned. For raw strings the following can be used:

Get-ChildItem -Recurse | ?{ $_.PSIsContainer } | % { $_.FullName }

The difference matters if the value is concatenated to a string:

  • with Select-Object suprisingly foo\@{FullName=bar}
  • with the ForEach-operator the expected: foo\bar

Solution 10 - Powershell

Use:

Get-ChildItem \\myserver\myshare\myshare\ -Directory | Select-Object -Property name |  convertto-csv -NoTypeInformation  | Out-File c:\temp\mydirectorylist.csv

Which does the following

  • Get a list of directories in the target location: Get-ChildItem \\myserver\myshare\myshare\ -Directory
  • Extract only the name of the directories: Select-Object -Property name
  • Convert the output to CSV format: convertto-csv -NoTypeInformation
  • Save the result to a file: Out-File c:\temp\mydirectorylist.csv

Solution 11 - Powershell

You'll want to use Get-ChildItem to recursively get all folders and files first. And then pipe that output into a Where-Object clause which only take the files.

# one of several ways to identify a file is using GetType() which
# will return "FileInfo" or "DirectoryInfo"
$files = Get-ChildItem E:\ -Recurse | Where-Object {$_.GetType().Name -eq "FileInfo"} ;

foreach ($file in $files) {
  echo $file.FullName ;
}






Solution 12 - Powershell

A bit more readable and simple approach could be achieved with the script below:

$Directory = "./"
Get-ChildItem $Directory -Recurse | % {
    if ($_.Attributes -eq "Directory") {
        Write-Host $_.FullName
    }
}

Hope this helps!

Solution 13 - Powershell

My solution is based on the TechNet article Fun Things You Can Do With the Get-ChildItem Cmdlet.

Get-ChildItem C:\foo | Where-Object {$_.mode -match "d"}

I used it in my script, and it works well.

Solution 14 - Powershell

Use this one:

Get-ChildItem -Path \\server\share\folder\ -Recurse -Force | where {$_.Attributes -like '*Directory*'} | Export-Csv -Path C:\Temp\Export.csv -Encoding "Unicode" -Delimiter ";"

Solution 15 - Powershell

To answer the original question specifically (using IO.FileAttributes):

Get-ChildItem c:\mypath -Recurse | Where-Object {$_.Attributes -and [IO.FileAttributes]::Directory}

I do prefer Marek's solution though (Where-Object { $_ -is [System.IO.DirectoryInfo] }).

Solution 16 - Powershell

This question is well and truly answered but thought I'd add something extra as I've just been looking at this.

Get-ChildItem happens to produce two types of objects whereas most commands produce just one.

FileInfo and DirectoryInfo are returned.

You can see this by viewing the 'members' available to this command like so:

Get-ChildItem | Get-Member
  • TypeName: System.IO.DirectoryInfo
  • TypeName: System.IO.FileInfo

You'll see the various methods and properties available to each type. Note that there are differences. For example that the FileInfo object has a length property but the DirectoryInfo object doesn't.

Anyway, technically, we can return just the directories by isolating the DirectoryInfo object

Get-ChildItem | Where-Object {$_.GetType().Name -eq "DirectoryInfo"}

Obviously as the top answer states the most straightforward solution is to simply use Get-ChildItem -Directory but we now know how to work with multple object types in future :)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionPeter HullView Question on Stackoverflow
Solution 1 - PowershellxcudView Answer on Stackoverflow
Solution 2 - PowershelliraSenthilView Answer on Stackoverflow
Solution 3 - PowershellSachin JosephView Answer on Stackoverflow
Solution 4 - PowershellCarlos NunezView Answer on Stackoverflow
Solution 5 - PowershellMarek DzikiewiczView Answer on Stackoverflow
Solution 6 - PowershellBillView Answer on Stackoverflow
Solution 7 - PowershelljyggorathView Answer on Stackoverflow
Solution 8 - PowershellWesleyView Answer on Stackoverflow
Solution 9 - PowershellsevenforceView Answer on Stackoverflow
Solution 10 - PowershellMarty GomezView Answer on Stackoverflow
Solution 11 - PowershellsonjzView Answer on Stackoverflow
Solution 12 - PowershellZorayrView Answer on Stackoverflow
Solution 13 - PowershellSarrusView Answer on Stackoverflow
Solution 14 - PowershellHansliView Answer on Stackoverflow
Solution 15 - PowershellNicolas MelayView Answer on Stackoverflow
Solution 16 - Powershelluser5947282View Answer on Stackoverflow