TEMA about_Foreach DESCRIPCIÓN BREVE Describe un comando de lenguaje que se puede utilizar para recorrer todos los elementos de una colección de elementos. DESCRIPCIÓN DETALLADA La instrucción Foreach (también denominada bucle Foreach) es una construcción de lenguaje para recorrer paso a paso (en iteración) una serie de valores de una colección de elementos. El tipo de colección más sencillo y típico para recorrer es una matriz. En un bucle Foreach, es habitual ejecutar uno o varios comandos respecto a cada elemento de una matriz. Sintaxis A continuación se muestra la sintaxis de la instrucción Foreach: foreach ($<elemento> in $<colección>){<lista de instrucciones>} Instrucción Foreach fuera de una canalización de comando La parte de la instrucción Foreach incluida entre paréntesis representa una variable y una colección que se recorrerá en iteración. Windows PowerShell crea la variable ($<elemento>) automáticamente cuando se ejecuta el bucle Foreach. Antes de cada iteración en el bucle, la variable se establece en un valor de la colección. El bloque que sigue a la instrucción Foreach {<lista de instrucciones>} contiene una colección de comandos que se ejecutan respecto a cada elemento de una colección. Ejemplos Por ejemplo, el bucle Foreach del siguiente ejemplo muestra los valores de la matriz $letterArray. $letterArray = "a","b","c","d" foreach ($letter in $letterArray) { Write-Host $letter } En este ejemplo, la matriz $letterArray se crea e inicializa con los valores de cadena "a", "b", "c" y "d". La primera vez que se ejecuta la instrucción Foreach, establece la variable $letter en el valor del primer elemento de $letterArray ("a"). A continuación, utiliza el cmdlet Write-Host para mostrar la letra a. La siguiente vez que se recorre el bucle, $letter se establece en "b", y así sucesivamente. Después de que el bucle Foreach muestre la letra d, Windows PowerShell cierra el bucle. La instrucción Foreach completa debe aparecer en una sola línea para que se ejecute como un comando en el símbolo del sistema de Windows PowerShell. En cambio, la instrucción Foreach completa no tiene que aparecer en una única línea si el comando se incluye en un archivo de script .ps1. Pueden usarse también instrucciones Foreach junto con cmdlets que devuelvan una colección de elementos. En el siguiente ejemplo, la instrucción Foreach recorre la lista de elementos devuelta por el cmdlet Get-ChildItem. foreach ($file in Get-ChildItem) { Write-Host $file } El ejemplo se puede perfeccionar usando una instrucción If para limitar los resultados que se devuelven. En el siguiente ejemplo, la instrucción Foreach realiza la misma operación de bucle que en el ejemplo anterior, pero se agrega una instrucción If para limitar los resultados a los archivos con un tamaño superior a 100 kilobytes (KB): foreach ($file in Get-ChildItem) { if ($file.length -gt 100k) { Write-Host $file } } En este ejemplo, el bucle Foreach usa una propiedad de la variable $file para realizar una operación de comparación ($file.length -gt 100k). La variable $file contiene todas las propiedades del objeto devuelto por el cmdlet Get-ChildItem. En consecuencia, puede devolverse más información, sin limitarse al nombre del archivo. En el ejemplo siguiente, Windows PowerShell devuelve la longitud y la hora del último acceso en la lista de instrucciones: foreach ($file in Get-ChildItem) { if ($file.length -gt 100k) { Write-Host $file Write-Host $file.length Write-Host $file.lastaccesstime } } En este ejemplo, no hay que limitarse a ejecutar un solo comando en una lista de instrucciones. También se puede usar una variable fuera de un bucle Foreach e incrementarla dentro del bucle. En el ejemplo siguiente se cuentan los archivos cuyo tamaño es superior a 100 KB: $i = 0 foreach ($file in Get-ChildItem) { if ($file.length -gt 100k) { Write-Host $file "tamaño de archivo:" ($file.length / 1024).ToString("F0") KB $i = $i + 1 } } if ($i -ne 0) { Write-Host Write-Host $i " archivo(s) con más de 100 KB en el directorio actual."} else { Write-Host "No hay ningún archivo de más de 100 KB en el directorio actual." } En el ejemplo anterior, la variable $i se establece en 0 fuera del bucle y se incrementa dentro del bucle por cada archivo encontrado cuyo tamaño es superior a 100 KB. Cuando el bucle se cierra, una instrucción If evalúa el valor de $i para mostrar el recuento de todos los archivos que tienen más de 100 KB. O bien, muestra un mensaje que afirma que no se encontró ningún archivo que tuviera más de 100 KB. En el ejemplo anterior también se muestra cómo dar formato a los resultados de longitud de archivos: ($file.length / 1024).ToString("F0") El valor se divide entre 1.024 para mostrar los resultados en kilobytes y no en bytes, y después se aplica formato al valor resultante mediante el especificador de formato de punto fijo para quitar los valores decimales del resultado. El 0 hace que el especificador del formato no muestre ninguna posición decimal. Instrucción Foreach dentro de una canalización de comando Cuando Foreach aparece en una canalización de comandos, Windows PowerShell utiliza el alias de foreach, que llama al comando ForEach-Object. Cuando se usa el alias foreach en una canalización de comandos, no se incluye la sintaxis ($<elemento> in $<colección>) como en la instrucción Foreach. Esto es debido a que el comando anterior de la canalización proporciona esta información. La sintaxis del alias foreach cuando se utiliza en una canalización de comandos es la siguiente: <comando> | foreach {<bloqueComandos>} Por ejemplo, el bucle Foreach incluido en la siguiente canalización de comandos muestra los procesos cuyo espacio de trabajo (uso de memoria) es superior a 20 megabytes (MB). Windows PowerShell canaliza el resultado del comando Get-Process al alias foreach. Dentro del bloque de comandos del alias foreach, la variable $_.WS contiene el valor de la propiedad WS (conjunto de trabajo) que le ha pasado el cmdlet Get-Process. (La sección $_ de la declaración es una variable automática de Windows Script Host [WSH] y la sección WS es una propiedad). La instrucción If usa una instrucción condicional para determinar si el espacio de trabajo es superior a 20 MB (20.000.000 bytes). En caso afirmativo, se muestran el nombre del proceso (almacenado en la variable $_.name) y el tamaño del espacio de trabajo en megabytes.No se mostrará nada si ninguno de los espacios de trabajo de los procesos es superior a 20 MB. Write-Host "Procesos con espacios de trabajo mayores que 20 MB" Get-Process | foreach { if ($_.WS -gt 20m) { Write-Host $_.name ": " ($_.WS/1m).ToString("F0") MB -Separator "" } } El alias foreach también admite los bloques de comandos iniciales, en el centro y al final. Los bloques de comandos inicial y final se ejecutan una vez, mientras que el bloque de comandos central se ejecuta cada vez que el bucle Foreach recorre una colección o una matriz. La sintaxis del alias foreach en una canalización de comandos con un conjunto de bloques de comandos inicial, central y final es la siguiente: <comando> | foreach {<bloqueComandos inicial>}{<bloqueComandos central>}{<bloqueComandos final>} En el siguiente ejemplo se muestra el uso de los bloques de comandos inicial, central y final. Get-ChildItem | foreach { $fileCount = $directoryCount = 0}{ if ($_.PsIsContainer) {$directoryCount++} else {$fileCount++}}{ "$directoryCount directorios y $fileCount archivos"} El bloque de comandos inicial crea e inicializa dos variables en 0: {$fileCount = $directoryCount = 0} El bloque central evalúa si cada elemento devuelto por Get-ChildItem es un directorio o un archivo: {if ($_.PsIsContainer) {$directoryCount++} else {$fileCount++}} Si el elemento que se devuelve es un directorio, se incrementa en 1 la variable $directoryCount. Si el elemento no es un directorio, se incrementa en 1 la variable $fileCount. El bloque final se ejecuta cuando el bloque central completa su operación de bucle y, a continuación, devuelve los resultados de la operación: {"$directoryCount directorios y $fileCount archivos"} Con la estructura de bloques de comandos inicial, central y final y el operador de canalización, puede volver a escribir el ejemplo anterior a fin de buscar los archivos con un tamaño superior a 100 KB, como se muestra a continuación: Get-ChildItem | foreach{ $i = 0}{ if ($_.length -gt 100k) { Write-Host $_.name "tamaño del archivo:" ($_.length / 1024).ToString("F0") KB $i++ } }{ if ($i -ne 0) { Write-Host Write-Host "$i archivo(s) con más de 100 KB en el directorio actual." } else { Write-Host "No hay ningún archivo de más de 100 KB en el directorio actual."} } VEA TAMBIÉN about_Automatic_Variables about_If Foreach-Object