How do I get only directories using Get-ChildItem?

2019-01-10 01:44发布

问题:

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

回答1:

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

For PowerShell 3.0 and greater:

dir -Directory


回答2:

In PowerShell 3.0, it is simpler:

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


回答3:

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) and PowerShell Core 6.0 (Windows 10, Mac and Linux).



回答4:

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.



回答5:

Use:

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


回答6:

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"


回答7:

Less text is required with this approach:

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


回答8:

Use:

dir -Directory -Recurse | Select FullName

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



回答9:

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!



回答10:

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


回答11:

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


回答12:

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.



回答13:

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 ;
}


回答14:

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 ";"


回答15:

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] }).