una txt script por para navegar listar leer extension ejemplos crear copiar childitem carpeta buscar archivos archivo powershell powershell-v2.0

txt - ¿Cómo recuperar un directorio recursivo y una lista de archivos de PowerShell excluyendo algunos archivos y carpetas?



powershell listar archivos (3)

Aquí hay otra opción, que es menos eficiente pero más conciso. Así es como generalmente manejo este tipo de problema:

Get-ChildItem -Recurse ./targetdir -Exclude *.log | Where-Object { $_.FullName -notmatch ''//excludedir($|//)'' }

La expresión //excludedir($|//)'' permite excluir el directorio y sus contenidos al mismo tiempo.

Actualización: Por favor, compruebe la excelente respuesta de msorens para una falla de borde de caso con este enfoque, y una solución mucho más carnosa en general.

Quiero escribir un script de PowerShell que buscará recursivamente en un directorio, pero excluirá los archivos especificados (por ejemplo, *.log y myFile.txt ) y también excluirá los directorios especificados y sus contenidos (por ejemplo, myDir y todos los archivos y carpetas debajo de myDir ).

He estado trabajando con Get-ChildItem CmdLet y Where-Object CmdLet, pero parece que no puedo obtener este comportamiento exacto.


El cmdlet Get-ChildItem tiene un parámetro -Exclude que es tentador de usar, pero no funciona para filtrar directorios completos por lo que puedo decir. Pruebe algo como esto:

function GetFiles($path = $pwd, [string[]]$exclude) { foreach ($item in Get-ChildItem $path) { if ($exclude | Where {$item -like $_}) { continue } if (Test-Path $item.FullName -PathType Container) { $item GetFiles $item.FullName $exclude } else { $item } } }


Me gusta la respuesta de Keith Hill, excepto que tiene un error que evita que vuelva a aparecer en los últimos dos niveles. Estos comandos manifiestan el error:

New-Item level1/level2/level3/level4/foobar.txt -Force -ItemType file cd level1 GetFiles . xyz | % { $_.fullname }

Con el código original de Hill obtienes esto:

.../level1/level2 .../level1/level2/level3

Aquí hay una versión corregida y ligeramente refactorizada:

function GetFiles($path = $pwd, [string[]]$exclude) { foreach ($item in Get-ChildItem $path) { if ($exclude | Where {$item -like $_}) { continue } $item if (Test-Path $item.FullName -PathType Container) { GetFiles $item.FullName $exclude } } }

Con esa corrección de errores, obtienes esta salida corregida:

.../level1/level2 .../level1/level2/level3 .../level1/level2/level3/level4 .../level1/level2/level3/level4/foobar.txt

También me gusta la respuesta de ajk por su concisión, aunque, como él señala, es menos eficiente. La razón por la que es menos eficiente, por cierto, es porque el algoritmo de Hill deja de atravesar un subárbol cuando encuentra un objetivo de transición mientras continúa el de ajk. Pero la respuesta de ajk también adolece de un defecto, al que llamo la trampa de los ancestros . Considere un camino como este que incluye el mismo componente de ruta (es decir, subdir2) dos veces:

/usr/testdir/subdir2/child/grandchild/subdir2/doc

Establezca su ubicación en algún punto intermedio, por ejemplo, cd /usr/testdir/subdir2/child , luego ejecute el algoritmo de ajk para filtrar el subdir2 inferior y no obtendrá ningún resultado, es decir, filtra todo por la presencia de subdir2 más alto en el camino. Sin embargo, este es un caso de esquina, y no es probable que lo golpeen con frecuencia, por lo que no descartaría la solución de ajk debido a este único problema.

No obstante, ofrezco aquí una tercera alternativa , una que no tiene ninguno de los dos errores anteriores. Aquí está el algoritmo básico, completo con una definición de conveniencia para la ruta o las rutas para podar: solo necesita modificar $excludeList a su propio conjunto de objetivos para usarlo:

$excludeList = @("stuff","bin","obj*") Get-ChildItem -Recurse | % { $pathParts = $_.FullName.substring($pwd.path.Length + 1).split("/"); if ( ! ($excludeList | where { $pathParts -like $_ } ) ) { $_ } }

Mi algoritmo es razonablemente conciso, pero, como el de ajk, es menos eficiente que el de Hill (por la misma razón: no deja de atravesar los subárboles en los objetivos de poda). Sin embargo, mi código tiene una ventaja importante sobre Hill''s: ¡puede canalizarse! Por lo tanto, es posible encajar en una cadena de filtro para crear una versión personalizada de Get-ChildItem, mientras que el algoritmo recursivo de Hill, por sí solo, no puede hacerlo. El algoritmo de ajk se puede adaptar también al uso de la interconexión, pero especificar el elemento o los elementos que se excluirán no es tan limpio, está incrustado en una expresión regular en lugar de una simple lista de elementos que he utilizado.

He empaquetado mi código de poda de árboles en una versión mejorada de Get-ChildItem. Aparte de mi nombre poco imaginativo, Get-EnhancedChildItem estoy entusiasmado y lo he incluido en mi biblioteca de código abierto Powershell . Incluye varias otras capacidades nuevas además de la poda de árboles. Además, el código está diseñado para ser extensible: si desea agregar una nueva capacidad de filtrado, es sencillo de hacer. Básicamente, se llama primero a Get-ChildItem y se canaliza a cada filtro sucesivo que se activa a través de los parámetros del comando. Por lo tanto, algo como esto ...

Get-EnhancedChildItem –Recurse –Force –Svn –Exclude *.txt –ExcludeTree doc*,man -FullName -Verbose

... se convierte internamente en esto:

Get-ChildItem | FilterExcludeTree | FilterSvn | FilterFullName

Cada filtro debe cumplir con ciertas reglas: aceptar los objetos FileInfo y DirectoryInfo como entradas, generar lo mismo que las salidas, y usar stdin y stdout para que pueda insertarse en una interconexión. Aquí está el mismo código refactorizado para ajustarse a estas reglas:

filter FilterExcludeTree() { $target = $_ Coalesce-Args $Path "." | % { $canonicalPath = (Get-Item $_).FullName if ($target.FullName.StartsWith($canonicalPath)) { $pathParts = $target.FullName.substring($canonicalPath.Length + 1).split("/"); if ( ! ($excludeList | where { $pathParts -like $_ } ) ) { $target } } } }

La única pieza adicional aquí es la función Coalesce-Args (que se encuentra en esta publicación de Keith Dahlby), que simplemente envía el directorio actual por el conducto en el caso de que la invocación no especifique ninguna ruta.

Debido a que esta respuesta es bastante larga, en lugar de entrar en más detalles sobre este filtro, remito al lector interesado a mi artículo recientemente publicado en Simple-Talk.com titulado Practical PowerShell: podar árboles de archivos y extender cmdlets, donde analizo Get-EnhancedChildItem. a una longitud aún mayor. Sin embargo, una última cosa que mencionaré es otra función en mi biblioteca de código abierto, New-FileTree , que te permite generar un árbol de archivos ficticio para propósitos de prueba para que puedas ejercitar cualquiera de los algoritmos anteriores. Y cuando experimente con cualquiera de estos, le recomiendo que haga un enlace a % { $_.fullname } como lo hice en el primer fragmento de código para obtener más resultados útiles para examinar.