Come posso ottenere solo le directory usando Get-ChildItem?


242

Sto usando PowerShell 2.0 e voglio eseguire il pipe di tutte le sottodirectory di un determinato percorso. Il seguente comando genera tutti i file e le directory, ma non riesco a capire come filtrare i file.

Get-ChildItem c:\mypath -Recurse

Ho provato a usare $_.Attributesper ottenere gli attributi, ma poi non so come costruire un'istanza letterale System.IO.FileAttributesper confrontarla. In cmd.exeesso sarebbe

dir /b /ad /s

Risposte:


292

Per versioni di PowerShell inferiori a 3.0:

L' FileInfooggetto restituito da Get-ChildItemha una proprietà "base", PSIsContainer. Vuoi selezionare solo quegli elementi.

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

Se vuoi i nomi di stringa grezzi delle directory, puoi farlo

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

Per PowerShell 3.0 e versioni successive:

dir -Directory

20
Vorrei che fosse aliasato "IsFolder".
xcud,

5
xcud: non tutte le gerarchie rappresentate da un PSDrive sono basate su cartelle.
Joey,

10
Il divario semantico tra "container" e "cartella" non è uno che puoi guidare un camion.
xcud,

5
@xcud: vedi la risposta di iraSenthil. -Directory e -File funziona anche su Get-ChildItem. Non è necessario utilizzare direttamente l'attributo PSIsContainer.
Wouter,

(Get-ChildItem |? {$ _. PSIsContainer} | Seleziona nome). Nome
Jose Ortega,

195

In PowerShell 3.0, è più semplice:

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

33
dir è un alias di Get-ChildItem
Chip McCormick,

1
@crashmstr Sei sicuro? Ho controllato la mia PS4.0. Per me, direra aliasato Get-ChildIteme le opzioni -Directorye -Filefunzionavano come descritto. Ho usato i comandi echo $PSVersionTable, help dir, dir -Directorye dir -Filedi venire con questo commento.
Peter Hull,

3
Questa dovrebbe essere la risposta
Chris S

2
lse dirsono alias di Get-ChildItemraccogliere il tuo veleno
Kolob Canyon,

53

Uso

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

Se preferisci gli alias, usa

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

o

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

Per richiamare anche le sottodirectory, aggiungi l' -ropzione.

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

Testato su 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 : su PowerShell Core, i collegamenti simbolici non vengono seguiti quando si specifica l' -ropzione. Per seguire i collegamenti simbolici, specificare l' -FollowSymlinkopzione con -r.

Nota 2 : PowerShell è ora multipiattaforma, dalla versione 6.0. La versione multipiattaforma era originariamente chiamata PowerShell Core, ma la parola "Core" è stata eliminata da PowerShell 7.0+.

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


2
Questo non funzionerà in Powershell 2.0, che era l'esigenza specifica dell'OP. i - [/ Dir / Directory] non sono parametri validi in Powershell 2.0
Ben Personick

21

Un approccio più pulito:

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

Mi chiedo se PowerShell 3.0 abbia uno switch che restituisce solo directory; sembra una cosa logica da aggiungere.


1
FYI powershell 3.0 aggiunge i flag -Directorye-File
WickyNilliams,


6

Da PowerShell v2 e versioni successive (k rappresenta la cartella in cui si sta iniziando la ricerca):

Get-ChildItem $Path -attributes D -Recurse

Se vuoi solo nomi di cartelle e nient'altro, usa questo:

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

Se stai cercando una cartella specifica, puoi utilizzare quanto segue. In questo caso, sto cercando una cartella chiamata myFolder:

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

E usando PS 3.0 o 4.0?
Kiquenet,

5
Il parametro Attributes non sembra essere in PS2, dà un errore "Impossibile trovare un parametro che corrisponde al nome del parametro 'Attributes'". Funziona bene su PS3.
WileCau,

5

È richiesto meno testo con questo approccio:

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

Questo è quello che vorrei usare.
David Betz,

2
Ancora più breve: ls -r | ? {$ _. mode -match "d"}
jyggorath

Questo non trova cartelle compresse
Charles Lambert,

7
Perché una cartella compressa è un file zip
user1594322

Non è sempre utile ricorrere a tutto. Potresti avere un albero estremamente profondo e folto in cui sei interessato solo alle directory esattamente a due livelli; la ricerca di trenta livelli è una perdita di tempo.
Ross Presser,

4

Uso:

dir -Directory -Recurse | Select FullName

Questo ti darà un output della struttura radice con il nome della cartella solo per le directory.


3

Uso:

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

Che fa quanto segue

  • Ottieni un elenco di directory nella posizione di destinazione: Get-ChildItem \\myserver\myshare\myshare\ -Directory
  • Estrai solo il nome delle directory: Select-Object -Property name
  • Converti l'output in formato CSV: convertto-csv -NoTypeInformation
  • Salva il risultato in un file: Out-File c:\temp\mydirectorylist.csv

2
Sarebbe bello se puoi spiegare ogni passaggio in modo che più persone possano vedere cosa sta succedendo.
jazzurro,

Questo non funzionerà in Powershell 2.0, che era l'esigenza specifica dell'OP. i - [/ Dir / Directory] non sono parametri validi in Powershell 2.0
Ben Personick

2

Un approccio un po 'più leggibile e semplice potrebbe essere raggiunto con lo script seguente:

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

Spero che questo ti aiuti!


2

Ti consigliamo di utilizzare Get-ChildItem per ottenere prima ricorsivamente tutte le cartelle e i file. E quindi reindirizzare l'output in una clausola Where-Object che accetta solo i file.

# 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

La risposta accettata menziona

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

per ottenere una "stringa non elaborata". Ma in realtà Selected.System.IO.DirectoryInfoverranno restituiti oggetti di tipo . Per le stringhe non elaborate è possibile utilizzare:

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

La differenza è importante se il valore è concatenato a una stringa:

  • con Select-Objectsorprendentementefoo\@{FullName=bar}
  • con l' ForEachoperatore il previsto:foo\bar

1
Select-Object restituirà effettivamente oggetti di tipo PSCustomObject. Mentre puoi usare% (che è ForEach-Object) per ottenere le stringhe grezze come hai fatto tu, puoi anche usareSelect-Object -ExpandProperty FullName
JamesQMurphy


0

Usa questo:

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

0

Per rispondere in modo specifico alla domanda originale (utilizzando IO.FileAttributes):

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

Preferisco la soluzione di Marek ( Where-Object { $_ -is [System.IO.DirectoryInfo] }).

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.