Как получить только каталоги, использующие 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, основана на папках.
Джои

10
Семантический разрыв между «контейнером» и «папкой» не тот, через который вы можете проехать на грузовике.
xcud

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

(Get-ChildItem |? {$ _. PSIsContainer} | Выбрать имя). Имя
Хосе Ортега

195

В PowerShell 3.0 это проще:

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

33
dir - это псевдоним Get-ChildItem
Чип Маккормик

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, который был специфической потребностью в OP. - [/ Dir / Directory] не являются допустимыми параметрами в Powershell 2.0
Ben

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?
Kiquenet

5
Параметр Attributes, по-видимому, отсутствует в PS2, он выдает ошибку «Не удается найти параметр, который соответствует имени параметра« Attributes »». Работает нормально в PS3.
WileCau

5

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

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

Это тот, который я бы использовал.
Дэвид Бетц

2
Еще короче: ls -r | ? {$ _. mode -match "d"}
jyggorath

Это не находит сжатые папки
Чарльз Ламберт

7
Потому что сжатая папка - это zip-файл
user1594322

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

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, который был специфической потребностью в OP. - [/ Dir / Directory] не являются допустимыми параметрами в Powershell 2.0
Ben

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.