arrays powershell get-childitem

arrays - Combine los resultados de dos llamadas distintas de Get-ChildItem en una sola variable para hacer el mismo procesamiento en ellas



powershell (5)

Estoy tratando de escribir un script de PowerShell para construir una lista de archivos, de varios directorios. Después de que todos los directorios se hayan agregado a la lista principal, me gustaría hacer el mismo procesamiento en todos los archivos.

Esto es lo que tengo:

$items = New-Object Collections.Generic.List[IO.FileInfo] $loc1 = @(Get-ChildItem -Path "//server/C$/Program Files (x86)/Data1/" -Recurse) $loc2 = @(Get-ChildItem -Path "//server/C$/Web/DataStorage/" -Recurse) $items.Add($loc1) # This line fails (the next also fails) $items.Add($loc2) # Processing code is here

que falla con este error:

No se puede convertir el argumento "0", con el valor: "System.Object []", para "Agregar" al tipo "System.IO.FileInfo": "No se puede convertir el valor" System.Object [] "del tipo" System. Objeto [] "para escribir" System.IO.FileInfo ".

Estoy interesado principalmente en cuál es el enfoque correcto para este tipo de situación. Me doy cuenta de que mi código es una forma muy C de hacerlo: si hay una forma más PowerShell de realizar la misma tarea, estoy totalmente a favor. La clave es que el número de $loc#''s puede cambiar con el tiempo, por lo que agregar y eliminar uno o dos debería ser fácil en el código resultante.


La respuesta de Keith es a la manera de PowerShell: simplemente use @ (...) + @ (...).

Si realmente desea una Lista de tipos seguros [IO.FileInfo], entonces necesita utilizar AddRange y convertir la matriz de objetos en una matriz de FileInfo. También debe asegurarse de no obtener ningún objeto DirectoryInfo, o bien necesita usar IO.FileSystemInfo como su tipo de lista:

Por lo tanto, evitar directorios:

$items = New-Object Collections.Generic.List[IO.FileInfo] $items.AddRange( ([IO.FileSystemInfo[]](ls ''//server/C$/Program Files (x86)/Data1/' -r | Where { -not $_.PSIsContainer } )) ) $items.AddRange( ([IO.FileSystemInfo[]](ls ''//server/C$/Web/DataStorage/' -r | Where { -not $_.PSIsContainer } )) )

O use FileSystemInfo (la clase base común de FileInfo y DirectoryInfo):

$items = New-Object Collections.Generic.List[IO.FileSystemInfo] $items.AddRange( ([IO.FileSystemInfo[]](ls ''//server/C$/Program Files (x86)/Data1/' -r)) ) $items.AddRange( ([IO.FileSystemInfo[]](ls ''//server/C$/Web/DataStorage/' -r)) )


Aquí hay una manera tal vez incluso más de PowerShell-ish que no necesita concatenación de partes o agregar elementos explícitos al resultado en absoluto:

# Collect the results by two or more calls of Get-ChildItem # and perhaps do some other job (but avoid unwanted output!) $result = .{ # Output items Get-ChildItem C:/TEMP/_100715_103408 -Recurse # Some other job $x = 1 + 1 # Output some more items Get-ChildItem C:/TEMP/_100715_110341 -Recurse #... } # Process the result items $result

Pero el código dentro del bloque de script debe escribirse un poco más cuidadosamente para evitar la salida no deseada mezclada con elementos del sistema de archivos.

EDITAR: Alternativamente, y quizás más efectivamente, en lugar de .{ ... } podemos usar @( ... ) o $( ... ) donde ... representa el código que contiene varias llamadas de Get-ChildItem .


Desde get-help get-childitem: -Path Especifica una ruta a una o más ubicaciones. Se permiten comodines. La ubicación predeterminada es el directorio actual (.).

$items = get-childitem ''//server/C$/Program Files (x86)/Data1/',''//server/C$/Web/DataStorage/' -Recurse


No estoy seguro de que necesites una lista genérica aquí. Puedes usar una matriz de PowerShell, por ejemplo:

$items = @(Get-ChildItem ''//server/C$/Program Files (x86)/Data1/' -r) $items += @(Get-ChildItem ''//server/C$/Web/DataStorage/' -r)

Los arreglos de PowerShell se pueden concatenar usando += .


-Filter es más -Include que -Include , por lo que si no tiene muchas extensiones diferentes, simplemente concatenar dos listas filtradas puede ser más rápido.

$files = Get-ChildItem -Path "H:/stash/" -Filter *.rdlc -Recurse $files += Get-ChildItem -Path "H:/stash/" -Filter *.rdl -Recurse

Comparé la salida con un temporizador como este:

$stopwatch = [System.Diagnostics.Stopwatch]::StartNew() # Do Stuff Here $stopwatch.Stop() Write-Host "$([Math]::Round($stopwatch.Elapsed.TotalSeconds)) seconds ellapsed"