Як отримати лише каталоги за допомогою Get-ChildItem?


242

Я використовую PowerShell 2.0 і хочу вивести всі підкаталоги певного шляху. Наступна команда виводить усі файли та каталоги, але я не можу зрозуміти, як відфільтрувати файли.

Get-ChildItem c:\mypath -Recurse

Я намагався використовувати $_.Attributesатрибути, але тоді я не знаю, як побудувати буквальний екземпляр System.IO.FileAttributesпорівняння. В cmd.exeньому було б

dir /b /ad /s

Відповіді:


292

Для версій PowerShell менше 3,0:

FileInfoОб'єкт , що повертається Get-ChildItemмає властивість «базовий», PSIsContainer. Ви хочете вибрати лише ті елементи.

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

Якщо ви хочете необмежених імен рядків каталогів, ви можете це зробити

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

Для PowerShell 3.0 і новіших версій:

dir -Directory

20
Побажання, яке було відчужено "IsFolder".
xcud

5
xcud: не кожна ієрархія, представлена ​​PSDrive, базується на папках.
Joey

10
Семантичний проміжок між "контейнером" і "папкою" - це не той, через який можна проїхати вантажівку.
xcud

5
@xcud: Дивіться відповідь iraSenthil. -Directory і -File також працює на Get-ChildItem. Не потрібно безпосередньо використовувати атрибут PSIsContainer.
Wouter

(Get-ChildItem | {$ _ PsIsContainer.} |? Виберіть Ім'я) .Name
Jose Ortega

195

У PowerShell 3.0 простіше:

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

33
Режисер - псевдонім Get-ChildItem
Chip McCormick,

1
@crashmstr Ви впевнені? Я перевірив свій PS4.0. Для мене це dirбуло відчужене Get-ChildItem, -Directoryі -Fileваріанти та варіанти працювали, як описано. Я використовував команди echo $PSVersionTable, help dir, dir -Directoryі dir -Fileпридумати з цим коментарем.
Пітер Халл

3
Це має бути відповідь
Кріс С

2
lsі dirє псевдонімом Get-ChildItemвибору отрути
Колобський каньйон

53

Використовуйте

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

Якщо ви віддаєте перевагу псевдоніми, використовуйте

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

або

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

Для повторного запуску підкаталогів додайте -rпараметр.

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

Тестовано на PowerShell 4.0, PowerShell 5.0 (Windows 10), PowerShell Core 6.0 (Windows 10, Mac та Linux) та PowerShell 7.0 (Windows 10, Mac та Linux).

Примітка . У програмі PowerShell Core символьні посилання не вказуються, коли ви вказуєте -rкомутатор. Щоб слідувати символьним посиланням, вкажіть -FollowSymlinkперемикач за допомогою -r.

Примітка 2 : PowerShell тепер є платформою, починаючи з версії 6.0. Версія для крос-платформ спочатку називалася PowerShell Core, але слово "Core" було відмінено з моменту PowerShell 7.0+.

Документація Get-ChildItem: https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.management/get-childitem


2
Це не спрацює в Powershell 2.0, що було специфічною потребою ОП. - [/ Dir / Directory] недійсні параметри в Powershell 2.0
Ben Personick

21

Більш чистий підхід:

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

Цікаво, чи має PowerShell 3.0 комутатор, який повертає лише каталоги; здається, що додати щось логічне.


1
FYI powershell 3.0 додає -Directoryі -Fileпрапори
WickyNilliams


6

З PowerShell v2 та новіших версій (k являє собою папку, в якій ви починаєте пошук):

Get-ChildItem $Path -attributes D -Recurse

Якщо ви хочете лише імена папок, і нічого іншого, використовуйте це:

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

Якщо ви шукаєте певну папку, ви можете скористатися наступною. У цьому випадку я шукаю папку під назвою myFolder:

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

А за допомогою PS 3.0 o 4.0?
Кікенет

5
Параметр Attributes, схоже, не є у PS2, він дає помилку "Неможливо знайти параметр, який відповідає назві параметра" Attributes "". Це працює нормально в PS3.
WileCau

5

При такому підході потрібно менше тексту:

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

Це той, який я б використовував.
Девід Бетц

2
Ще коротше: ls -r | ? {$ _. mode -match "d"}
jyggorath

Тут не знаходяться стислі папки
Charles Lambert

7
Оскільки
стискана

Не завжди корисно повторювати все. У вас може бути надзвичайно глибоке і кущисте дерево, де вас цікавлять лише каталоги рівно на два рівні вниз; пошук тридцяти рівнів вниз - це марна трата часу.
Росс Пресер

4

Використання:

dir -Directory -Recurse | Select FullName

Це дасть вам вихід кореневої структури з назвою папки лише для каталогів.


3

Використання:

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

Що робить наступне

  • Отримайте список каталогів у цільовому розташуванні: Get-ChildItem \\myserver\myshare\myshare\ -Directory
  • Витягніть лише назву каталогів: Select-Object -Property name
  • Перетворити вихід у формат CSV: convertto-csv -NoTypeInformation
  • Збережіть результат у файл: Out-File c:\temp\mydirectorylist.csv

2
Було б чудово, якщо ви зможете пояснити кожен крок, щоб більше людей могли бачити, що відбувається.
джазурро

Це не спрацює в Powershell 2.0, що було специфічною потребою ОП. - [/ Dir / Directory] недійсні параметри в Powershell 2.0
Ben Personick

2

Трохи більш читабельний і простий підхід можна досягти за допомогою сценарію нижче:

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

Сподіваюсь, це допомагає!


2

Ви хочете скористатися Get-ChildItem, щоб рекурсивно спочатку отримати всі папки та файли. А потім передайте цей висновок у пункт « Where-Object», який приймає лише файли.

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

1

Згадується прийнята відповідь

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

щоб отримати "сиру рядок". Але насправді об’єкти типу Selected.System.IO.DirectoryInfoбудуть повернуті. Для сирих рядків можна використовувати наступне:

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

Різниця має значення, якщо значення об'єднано в рядок:

  • з Select-Objectнадихаючимfoo\@{FullName=bar}
  • з ForEach-оператором очікувані:foo\bar

1
Select-Object фактично поверне об'єкти типу PSCustomObject. Хоча ви можете використовувати% (що є ForEach-Object), щоб отримати необроблені рядки, як ви робили, ви також можете використовуватиSelect-Object -ExpandProperty FullName
JamesQMurphy


0

Скористайтеся цим:

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

0

Щоб відповісти на оригінальне запитання конкретно (використовуючи IO.FileAttributes):

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

Я вважаю за краще рішення Марека, хоча ( Where-Object { $_ -is [System.IO.DirectoryInfo] }).

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.