Como obtenho apenas diretórios usando Get-ChildItem?

242

Estou usando o PowerShell 2.0 e quero canalizar todos os subdiretórios de um determinado caminho. O comando a seguir gera todos os arquivos e diretórios, mas não consigo descobrir como filtrar os arquivos.

Get-ChildItem c:\mypath -Recurse

Eu tentei usar $_.Attributespara obter os atributos, mas não sei como construir uma instância literal System.IO.FileAttributespara compará-la. Dentro cmd.exeseria

dir /b /ad /s
Peter Hull
fonte

Respostas:

292

Para versões do PowerShell menores que 3.0:

O FileInfoobjeto retornado por Get-ChildItempossui uma propriedade "base" PSIsContainer,. Você deseja selecionar apenas esses itens.

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

Se você quiser os nomes de cadeias brutas dos diretórios, poderá fazer

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

Para o PowerShell 3.0 e superior:

dir -Directory
xcud
fonte
20
Desejo que fosse alias de "IsFolder".
xcud
5
xcud: nem toda hierarquia representada por um PSDrive é baseada em pastas.
Joey
10
O espaço semântico entre "contêiner" e "pasta" não é aquele pelo qual você pode dirigir um caminhão.
Xcud
5
@xcud: Veja a resposta de iraSenthil. -Directory e -File também funciona em Get-ChildItem. Não há necessidade de usar o atributo PSIsContainer diretamente.
Wouter
(Get-ChildItem |? {$ _. PSIsContainer} | Selecionar nome) .Name
Jose Ortega
195

No PowerShell 3.0, é mais simples:

Get-ChildItem -Directory #List only directories
Get-ChildItem -File #List only files
iraSenthil
fonte
33
dir é um alias para Get-ChildItem
Chip McCormick
1
@crashmstr Você tem certeza? Eu verifiquei no meu PS4.0. Para mim, dirfoi um alias para Get-ChildItem, e as opções -Directorye -Filefuncionaram conforme descrito. Eu usei comandos echo $PSVersionTable, help dir, dir -Directorye dir -Filepara chegar a este comentário.
Peter Hull
3
Esta deve ser a resposta
Chris S
2
lse dirsão aliases de Get-ChildItemescolher o seu veneno
Kolob Canyon
53

Usar

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

Se você preferir aliases, use

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

ou

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

Para recursar subdiretórios também, adicione a -ropção

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

Testado no PowerShell 4.0, PowerShell 5.0 (Windows 10), PowerShell Core 6.0 (Windows 10, Mac e Linux) e PowerShell 7.0 (Windows 10, Mac e Linux).

Nota : No PowerShell Core, os links simbólicos não são seguidos quando você especifica a -ropção. Para seguir os links simbólicos, especifique a -FollowSymlinkopção com -r.

Nota 2 : O PowerShell agora é multiplataforma, desde a versão 6.0. A versão de plataforma cruzada era originalmente chamada PowerShell Core, mas a palavra "Core" foi removida desde o PowerShell 7.0+.

Documentação Get-ChildItem: https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.management/get-childitem

Sachin Joseph
fonte
2
Isso não funcionará no Powershell 2.0, que era a necessidade específica do OP. a - [/ Dir / Diretório] não são parâmetros válidos no PowerShell 2.0
Ben Personick
21

Uma abordagem mais limpa:

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

Gostaria de saber se o PowerShell 3.0 tem uma opção que retorna apenas diretórios; parece uma coisa lógica a acrescentar.

Carlos Nunez
fonte
1
FYI powershell 3.0 adiciona os -Directorye -Filebandeiras
WickyNilliams
12

Usar:

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

No PowerShell v2 e mais recente (k representa a pasta em que você está iniciando sua pesquisa):

Get-ChildItem $Path -attributes D -Recurse

Se você deseja apenas nomes de pastas e nada mais, use o seguinte:

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

Se você estiver procurando por uma pasta específica, poderá usar o seguinte. Nesse caso, estou procurando uma pasta chamada myFolder:

Get-ChildItem $Path -attributes D -Recurse -include "myFolder"
Conta
fonte
E usando o PS 3.0 ou 4.0?
Kanjet
5
O parâmetro Attributes não parece estar no PS2, ele fornece um erro "Não foi possível encontrar um parâmetro que corresponda ao nome do parâmetro 'Attributes'". Funciona bem no PS3.
WileCau
5

Menos texto é necessário com esta abordagem:

ls -r | ? {$_.mode -match "d"}
jyggorath
fonte
Este é o que eu usaria.
David Betz
2
Ainda mais curto: ls -r | ? {$ _. mode -match "d"}
jyggorath
Isso não encontrar pastas comprimidas
Charles Lambert
7
Como uma pasta compactada é um arquivo zip
user1594322
Nem sempre é útil retribuir tudo. Você poderia ter uma árvore extremamente profunda e espessa, onde você só está interessado em diretórios exatamente dois níveis abaixo; pesquisar trinta níveis abaixo é uma perda de tempo.
Ross Presser
4

Usar:

dir -Directory -Recurse | Select FullName

Isso fornecerá uma saída da estrutura raiz com o nome da pasta apenas para diretórios.

Wesley
fonte
3

Usar:

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

O que faz o seguinte

  • Obtenha uma lista de diretórios no local de destino: Get-ChildItem \\myserver\myshare\myshare\ -Directory
  • Extraia apenas o nome dos diretórios: Select-Object -Property name
  • Converta a saída para o formato CSV: convertto-csv -NoTypeInformation
  • Salve o resultado em um arquivo: Out-File c:\temp\mydirectorylist.csv
Marty Gomez
fonte
2
Seria ótimo se você pudesse explicar cada passo para que mais pessoas possam ver o que está acontecendo.
jazzurro
Isso não funcionará no Powershell 2.0, que era a necessidade específica do OP. a - [/ Dir / Diretório] não são parâmetros válidos no PowerShell 2.0
Ben Personick
2

Uma abordagem um pouco mais legível e simples pode ser alcançada com o script abaixo:

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

Espero que isto ajude!

Zorayr
fonte
2

Você desejará usar Get-ChildItem para obter recursivamente todas as pastas e arquivos primeiro. Em seguida, canalize essa saída para uma cláusula Where-Object que apenas aceita os arquivos.

# 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 ;
}
sonjz
fonte
1

A resposta aceita menciona

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

para obter uma "sequência bruta". Mas, na verdade, objetos do tipo Selected.System.IO.DirectoryInfoserão retornados. Para cadeias brutas, o seguinte pode ser usado:

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

A diferença importa se o valor for concatenado para uma sequência:

  • com Select-Objectsurpreendentementefoo\@{FullName=bar}
  • com o ForEachoperador o esperado:foo\bar
sevenforce
fonte
1
Select-Object retornará realmente objetos do tipo PSCustomObject. Enquanto você pode usar% (que é ForEach-Object) para obter as cordas matérias como você fez, você também pode usarSelect-Object -ExpandProperty FullName
JamesQMurphy
0

Use este:

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

Para responder especificamente à pergunta original (usando IO.FileAttributes):

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

Mas prefiro a solução de Marek ( Where-Object { $_ -is [System.IO.DirectoryInfo] }).

Nicolas Melay
fonte