¿Cómo obtengo solo directorios con Get-ChildItem?

242

Estoy usando PowerShell 2.0 y quiero canalizar todos los subdirectorios de una ruta determinada. El siguiente comando genera todos los archivos y directorios, pero no puedo entender cómo filtrar los archivos.

Get-ChildItem c:\mypath -Recurse

He intentado usar $_.Attributespara obtener los atributos, pero no sé cómo construir una instancia literal System.IO.FileAttributespara compararlo. En cmd.exeeso estaría

dir /b /ad /s
Peter Hull
fuente

Respuestas:

292

Para versiones de PowerShell inferiores a 3.0:

El FileInfoobjeto devuelto por Get-ChildItemtiene una propiedad "base", PSIsContainer. Desea seleccionar solo esos elementos.

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

Si desea los nombres de cadena sin formato de los directorios, puede hacer

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

Para PowerShell 3.0 y superior:

dir -Directory
xcud
fuente
20
Ojalá tuviera un alias de "IsFolder".
xcud
55
xcud: no todas las jerarquías representadas por un PSDrive están basadas en carpetas.
Joey
10
La brecha semántica entre "contenedor" y "carpeta" no puede atravesar un camión.
xcud
55
@xcud: Vea la respuesta de iraSenthil. -Directory y -File también funciona en Get-ChildItem. No es necesario usar el atributo PSIsContainer directamente.
Wouter
(Get-ChildItem |? {$ _. PSIsContainer} | Seleccionar nombre) .Nombre
Jose Ortega
195

En PowerShell 3.0, es más simple:

Get-ChildItem -Directory #List only directories
Get-ChildItem -File #List only files
iraSenthil
fuente
33
dir es un alias para Get-ChildItem
Chip McCormick
1
@crashmstr ¿Estás seguro? Revisé mi PS4.0. Para mí, dirtenía un alias Get-ChildItem, y las opciones -Directoryy -Filefuncionaron como se describe. Solía comandos echo $PSVersionTable, help dir, dir -Directoryy dir -Filepara llegar a este comentario.
Peter Hull
3
Esta debería ser la respuesta
Chris S
2
lsy dirson alias de Get-ChildItemelegir tu veneno
Kolob Canyon
53

Utilizar

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

Si prefiere alias, use

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

o

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

Para recurrir subdirectorios también, agregue la -ropción.

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

Probado en PowerShell 4.0, PowerShell 5.0 (Windows 10), PowerShell Core 6.0 (Windows 10, Mac y Linux) y PowerShell 7.0 (Windows 10, Mac y Linux).

Nota : En PowerShell Core, los enlaces simbólicos no se siguen cuando especifica el -rconmutador. Para seguir enlaces simbólicos, especifique el -FollowSymlinkinterruptor con -r.

Nota 2 : PowerShell ahora es multiplataforma, desde la versión 6.0. La versión multiplataforma se llamaba originalmente PowerShell Core, pero la palabra "Core" se ha eliminado desde PowerShell 7.0+.

Documentación de Get-ChildItem: https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.management/get-childitem

Sachin Joseph
fuente
2
Esto no funcionará en Powershell 2.0, que era la necesidad específica del OP. el - [/ Dir / Directory] no son parámetros válidos en Powershell 2.0
Ben Personick
21

Un enfoque más limpio:

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

Me pregunto si PowerShell 3.0 tiene un conmutador que solo devuelve directorios; Parece una cosa lógica agregar.

Carlos Nunez
fuente
1
FYI powershell 3.0 agrega las banderas -Directoryy-File
WickyNilliams
12

Utilizar:

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

Desde PowerShell v2 y posteriores (k representa la carpeta en la que está comenzando su búsqueda):

Get-ChildItem $Path -attributes D -Recurse

Si solo desea nombres de carpetas, y nada más, use esto:

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

Si está buscando una carpeta específica, puede usar lo siguiente. En este caso, estoy buscando una carpeta llamada myFolder:

Get-ChildItem $Path -attributes D -Recurse -include "myFolder"
Cuenta
fuente
¿Y con PS 3.0 o 4.0?
Kiquenet
55
El parámetro Atributos no parece estar en PS2, da un error "No se puede encontrar un parámetro que coincida con el nombre del parámetro 'Atributos'". Funciona bien en PS3.
WileCau
5

Se requiere menos texto con este enfoque:

ls -r | ? {$_.mode -match "d"}
jyggorath
fuente
Este es el que usaría.
David Betz
2
Aún más corto: ls -r | ? {$ _. mode -match "d"}
jyggorath
Esto no encuentra carpetas comprimidas
Charles Lambert
77
Porque una carpeta comprimida es un archivo zip
user1594322
No siempre es útil repetir todo. Podría tener un árbol extremadamente profundo y tupido donde solo le interesen los directorios exactamente dos niveles más abajo; buscar treinta niveles más abajo es una pérdida de tiempo.
Ross Presser
4

Utilizar:

dir -Directory -Recurse | Select FullName

Esto le dará una salida de la estructura raíz con el nombre de la carpeta solo para directorios.

Wesley
fuente
3

Utilizar:

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

Que hace lo siguiente

  • Obtenga una lista de directorios en la ubicación de destino: Get-ChildItem \\myserver\myshare\myshare\ -Directory
  • Extraiga solo el nombre de los directorios: Select-Object -Property name
  • Convierta la salida al formato CSV: convertto-csv -NoTypeInformation
  • Guarde el resultado en un archivo: Out-File c:\temp\mydirectorylist.csv
Marty Gomez
fuente
2
Sería genial si puedes explicar cada paso para que más personas puedan ver lo que está sucediendo.
jazzurro
Esto no funcionará en Powershell 2.0, que era la necesidad específica del OP. el - [/ Dir / Directory] no son parámetros válidos en Powershell 2.0
Ben Personick
2

Se podría lograr un enfoque un poco más legible y simple con el siguiente script:

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

¡Espero que esto ayude!

Zorayr
fuente
2

Querrá usar Get-ChildItem para obtener recursivamente todas las carpetas y archivos primero. Y luego canalice esa salida en una cláusula Where-Object que solo toma los archivos.

# 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
fuente
1

La respuesta aceptada menciona

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

para obtener una "cadena cruda". Pero, de hecho, los objetos de tipo Selected.System.IO.DirectoryInfoserán devueltos. Para cadenas sin formato se puede usar lo siguiente:

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

La diferencia es importante si el valor se concatena en una cadena:

  • con Select-Objectsorprendentefoo\@{FullName=bar}
  • con el ForEachoperador el esperado:foo\bar
sevenforce
fuente
1
Select-Object en realidad devolverá objetos del tipo PSCustomObject. Aunque se puede usar% (que es ForEach-Object) para obtener las cadenas primas como lo hizo, también se puede utilizarSelect-Object -ExpandProperty FullName
JamesQMurphy
0

Usa este:

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

Para responder la pregunta original específicamente (usando IO.FileAttributes):

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

Sin embargo, prefiero la solución de Marek ( Where-Object { $_ -is [System.IO.DirectoryInfo] }).

Nicolas Melay
fuente