Procesar datos CSV con Import-Csv y bucle ForEach en PowerShell

¿Alguna vez has tenido que realizar la misma tarea varias veces? Como crear múltiples usuarios en Active Directory uno por uno utilizando la interfaz gráfica, ¿o quizás iniciar sesión en un servidor para eliminar registros antiguos de algunas carpetas seleccionadas? Si tu respuesta es , entonces sabes que no estás solo. Es hora de dominar el Import-Csv de PowerShell y el bucle foreach.

No hay nada de malo en las tareas manuales; a veces es necesario. Pero cuando se trata de leer y procesar archivos CSV, el cmdlet de PowerShell Import-Csv y el bucle ForEach pueden ser de gran ayuda.

El cmdlet de PowerShell Import-Csv es una excelente manera de leer datos de una fuente tabulada, como un archivo CSV. Puedes usar el bucle ForEach para iterar sobre cada fila en los datos CSV.

En este artículo, aprenderás cómo utilizar esta poderosa combinación para automatizar tareas a granel, mundanas y repetitivas.

Si eres nuevo en el cmdlet Import-Csv y el bucle ForEach, o si deseas repasar lo que ya sabes, puedes visitar estos enlaces para obtener más información.

Manejo de archivos CSV en PowerShell con Import-Csv (bucle foreach)

Conceptos básicos: El bucle foreach de PowerShell

Prerrequisitos

Hay varios ejemplos y demostraciones en este artículo. Para seguir, necesitarás algunas cosas primero.

  • A script editor such as Visual Studio Code, Atom, or Notepad++. Use whichever one you’re comfortable with.
  • Windows PowerShell 5.1 o PowerShell Core 6+
  • Acceso a Exchange Online (opcional si seguirá el ejemplo práctico relacionado con Exchange Online).

Poniendo en práctica Import-Csv y el bucle ForEach

En las siguientes secciones se presentan varios ejemplos de cómo utilizar el cmdlet Import-Csv y el bucle ForEach que puede encontrar en escenarios del mundo real. Si bien estos ejemplos de PowerShell de importación CSV foreach son específicos para cada propósito, es crucial entender que el concepto y la técnica utilizados son los mismos.

Lectura y visualización de registros desde un archivo CSV

Quizás el uso más básico de Import-Csv y el bucle ForEach sea la lectura de registros desde un archivo y mostrarlos en la consola. La anatomía de un archivo CSV es similar a la de una base de datos. Tiene encabezados de columna y cada fila se considera un registro.

Por ejemplo, a continuación se muestra el contenido del archivo llamado employee.csv, que consta de tres columnas: EmployeeID, Name, y Birthday, y cuatro registros.

CSV containing employee records

El siguiente código importa el contenido del archivo employee.csv y luego envía los datos importados al cmdlet ForEach-Object. Luego, ForEach-Object recorrerá cada registro en el CSV importado para mostrar los valores concatenados en la consola. Copie el código a continuación y guárdelo como list-employee.ps1.

Nota: El tipo de bucle ForEach utilizado en este ejemplo es el cmdlet ForEach-Object. Consulta la sección “El cmdlet ForEach-Object” en este artículo.

Import-Csv .\employee.csv | ForEach-Object {
    Write-Host "$($_.Name), whose Employee ID is $($_.EmployeeID), was born on $($_.Birthday)."
}

Una vez que el script esté guardado, ejecútalo llamando a su nombre de archivo en PowerShell. Cuando se ejecute el script, deberías ver una salida similar a la captura de pantalla a continuación.

Imported CSV records displayed in the console

Búsqueda y visualización de registros desde CSV

En el ejemplo anterior, aprendiste cómo leer y mostrar todos los registros de un CSV. En este ejemplo, se utilizará el mismo archivo CSV employee.csv, pero esta vez crearás una función de PowerShell para buscar un EmployeeID en el CSV.

El fragmento de código a continuación es una función de PowerShell llamada Find-Employee que tiene solo un parámetro. El nombre del parámetro es EmployeeID y acepta un valor de EmployeeID para buscar en el CSV.

Antes de que esta función pueda ser utilizada, debe importarse primero a tu sesión de PowerShell. Hay dos formas de importar la función Find-Employee en la memoria:

  1. Copiando y pegando el siguiente código en PowerShell.
  2. Guardando el script como Find-Employee.ps1 e importándolo usando la técnica dot-sourcing.

Nota: El tipo de bucle ForEach utilizado en este ejemplo a continuación es la Declaración ForEach. Consulte la sección “La Declaración foreach” en este artículo.

Function Find-Employee {
    param (
        # El parámetro acepta el ID del empleado a buscar.
        [Parameter(Mandatory)]
        $EmployeeID
    )

    # Importar el contenido del archivo employee.csv y almacenarlo en la variable $employee_list.
    $employee_list = Import-Csv .\employee.csv

    # Iterar a través de todos los registros en el CSV
    foreach ($employee in $employee_list) {

        # Verificar si el ID del empleado del registro actual es igual al valor del parámetro EmployeeID.
        if ($employee.EmployeeID -eq $EmployeeID) {

            # Si se encuentra el EmployeeID, mostrar el registro en la consola.
            Write-Host "$($employee.Name), whose Employee ID is $($employee.EmployeeID), was born on $($employee.Birthday)."
        }
    }
}

Una vez que el código de la función se importa en la sesión de PowerShell, llámelo escribiendo el nombre de la función como se muestra a continuación.

Find-Employee

Cuando se ejecuta la función sin usar el parámetro EmployeeID, solicitará el valor del EmployeeID a buscar. Vea el ejemplo de salida a continuación.

Function to search a CSV file for a specific record

O bien, la función se puede ejecutar con el valor del parámetro EmployeeID especificado en tiempo de ejecución, como se muestra a continuación.

Find-Employee -EmployeeID 'E-2023'

Obtener el Uso del Espacio en Disco de Múltiples Servidores

Una tarea rutinaria común entre los administradores del sistema es monitorear el uso del espacio en disco de varios servidores. En lugar de iniciar sesión en cada servidor para verificar el uso del espacio en disco, puede crear una lista CSV que contenga nombres de servidor, letras de unidad y umbrales. Luego, utilizando PowerShell, importe el archivo CSV e itere a través de cada línea para ejecutar una consulta.

Para crear un script que obtenga el uso del espacio en disco de servidores remotos, primero crea una lista CSV con los siguientes encabezados:

  • servername – este es el nombre del servidor a consultar.
  • disk – esta es la letra de la unidad cuyo uso de espacio se recuperará.
  • threshold – esto define el umbral en GB. Si el espacio libre del disco es inferior a este valor, el informe mostrará un estado de advertencia.

El ejemplo a continuación muestra que hay cuatro registros enumerados. Tu archivo CSV será diferente según el número de servidores o discos a leer.

servername,disk,threshold
au-dc01,c,120
au-mail01,c,100
au-mail01,d,6
au-file01,c,120

Una vez que se finalice el CSV, guarda el archivo como servers.csv. Esto servirá como la lista de entrada que será importada por el script de PowerShell.

Para proporcionar un ejemplo de cómo obtener el uso del espacio en disco, copia el código a continuación en tu editor de scripts y guárdalo como diskReport.ps1. El script debe guardarse en la misma ubicación que la ruta del CSV.

$server_list = Import-Csv -Path .\servers.csv

foreach ($server in $server_list) {
    Get-WmiObject -Class Win32_logicaldisk -ComputerName ($server.servername) | `
        Where-Object { $_.DeviceID -match ($server.disk) } | `
        Select-Object `
    @{n = 'Server Name'; e = { $_.SystemName } }, `
    @{n = 'Disk Letter'; e = { $_.DeviceID } }, `
    @{n = 'Size (GB)'; e = { $_.Size / 1gb -as [int] } }, `
    @{n = 'Free (GB)'; e = { $_.FreeSpace / 1gb -as [int] } }, `
    @{n = 'Threshold (GB)'; e = { $server.Threshold } }, `
    @{n = 'Status'; e = {
            if (($_.FreeSpace / 1gb) -lt ($server.Threshold)) {
                return 'Warning'
            }
            else {
                return 'Normal'
            }
        }
    }
}

El script anterior realiza las siguientes acciones una vez que se ejecuta.

  • Importa el archivo csv llamado servers.csv y lo almacena en la variable $server_list.
  • Recorre la lista de servidores almacenados en la variable $server_list.
  • En cada iteración de los bucles foreach, la línea actual se representa mediante la variable $server.
  • Obtiene la información del disco de los servidores utilizando el cmdlet Get-WmiObject.
  • Seleccionar solo las propiedades relevantes para mostrar.
    Nombre del servidor – Este es el nombre del sistema que se está consultando.
    Letra de la unidad – La letra asignada a la unidad.
    Tamaño (GB) – El tamaño del disco en GB
    Libre (GB) – El tamaño del espacio libre en GB
    Umbral (GB) – El umbral definido en GB
    Estado – Si el valor Libre (GB) es menor que el valor Umbral (GB), el estado devuelto es ‘Advertencia’. De lo contrario, el estado será ‘Normal’

Habiendo guardado el archivo de script diskReport.ps1, ahora está listo para ejecutarse llamando a su nombre en PowerShell.

./diskReport.ps1

Una vez ejecutado, la captura de pantalla a continuación muestra la salida del script.

Disk space information gathered from multiple servers

La salida también se puede exportar a CSV. La exportación a CSV es útil cuando se necesita compartir el informe porque el archivo CSV exportado se puede enviar por correo electrónico o cargar en un recurso compartido de archivos o en un sitio de SharePoint. Asegúrese de consultar Export-Csv: La forma de PowerShell de tratar los archivos CSV como ciudadanos de primera clase si desea obtener más información sobre la exportación a CSV.

Creación de múltiples usuarios del Directorio Activo

En este punto, ya tendría una idea sólida sobre cómo usar Import-Csv y ForEach. Este próximo ejemplo lleva su aprendizaje un poco más lejos al agregar los cmdlets New-ADUser y Get-ADUser a la mezcla.

Supongamos que has recibido un archivo CSV new_employees.csv que contiene la lista de nuevos empleados del departamento de recursos humanos. Cada fila en el archivo CSV representa un usuario a bordo y tiene las siguientes columnas: Nombre, Apellido, Departamento, Estado, IDEmpleado y Oficina.

El nombre de usuario debe derivarse de la primera letra del nombre del empleado concatenada con el apellido (por ejemplo, bparr para el usuario Bob Parr).

CSV file containing new employees information for on-boarding

Una vez que se guarda el archivo CSV, el script a continuación utiliza Import-Csv para leer el archivo CSV new_employees.csv. Luego, itera a través de cada fila, pasando los valores a los parámetros apropiados de New-ADUser.

Import-Csv .\new_employees.csv | ForEach-Object {
    New-ADUser `
        -Name $($_.FirstName + " " + $_.LastName) `
        -GivenName $_.FirstName `
        -Surname $_.LastName `
        -Department $_.Department `
        -State $_.State `
        -EmployeeID $_.EmployeeID `
        -DisplayName $($_.FirstName + " " + $_.LastName) `
        -Office $_.Office `
        -UserPrincipalName $_.UserPrincipalName `
        -SamAccountName $_.SamAccountName `
        -AccountPassword $(ConvertTo-SecureString $_.Password -AsPlainText -Force) `
        -Enabled $True
}

Después de ejecutar el script, los nuevos usuarios deberían existir en Active Directory. Sin embargo, es una buena práctica confirmar que las cuentas de usuario realmente se hayan creado.

Usando el mismo archivo CSV new_employees.csv como referencia, el script a continuación ejecutará la importación CSV y un bucle para obtener los objetos ADUser que coincidan con los de la lista.

Import-Csv .\new_employees.csv | ForEach-Object {
	Get-AdUser $_.SamAccountName
}

Agregar una dirección de correo electrónico de proxy a la bandeja de entrada de Office 365

En la gestión de buzones de correo de Office 365, no es raro recibir solicitudes para agregar direcciones de proxy para varios usuarios. Comúnmente, en este tipo de solicitud, el administrador recibe una lista de usuarios y la dirección de correo electrónico que se agregará, similar al siguiente ejemplo de CSV.

The new_address.csv file contents

Nota: Antes de poder ejecutar cualquier cmdlet de Exchange Online en PowerShell, primero debes iniciar sesión en la shell de administración de Exchange Online.

Utilizando las funciones Import-Csv y el bucle ForEach en un script de PowerShell, la lista puede procesarse de una vez. El siguiente script muestra cómo hacerlo.

El script importa el contenido del archivo new_address.csv y lo almacena en la variable $user_list. Luego, utilizando el método foreach(), PowerShell recorre toda la lista de usuarios y utiliza los valores username y email en cada registro para agregar una nueva dirección de correo electrónico a cada buzón.

$user_list = Import-Csv .\new_address.csv

$user_list.foreach(
    {
        Set-Mailbox -Identity $_.username -EmailAddresses @{add="$($_.email)"}
    }
)

Una vez que se ejecuta el script, no se mostrará ninguna salida en la consola. La falta de salida en la pantalla significa que la nueva dirección de correo electrónico se agregó correctamente. Pero, ¿cómo puedes asegurarte de que se hayan agregado las direcciones de correo electrónico?

Utilizando el mismo archivo CSV new_address.csv como referencia, se puede verificar si las nuevas direcciones se agregaron o no mediante Import-Csv y ForEach.

El siguiente script importa el contenido del archivo new_address.csv y lo almacena en la variable $user_list. Luego, utilizando el método foreach(), PowerShell recorre toda la lista de usuarios para verificar si la nueva dirección de correo electrónico existe en la lista de direcciones proxy del buzón. Si se encuentra, el estado devolverá True; de lo contrario, el resultado será False.

$user_list = Import-Csv .\new_address.csv

$user_list.foreach(
    {
        $emailObj = (Get-Mailbox -Identity $_.username).EmailAddresses
        if ($emailObj -contains $_.email) {
            Write-Host "$($_.username) --> $($_.email) --> TRUE"
        }
        else {
            Write-Host "$($_.username) --> $($_.email) --> FALSE"
        }
    }
)

Cuando se ejecuta el script de validación, la salida debería verse como se muestra en la captura de pantalla a continuación. Observarás en la salida que el estado es todo TRUE, lo que significaría que las nuevas direcciones de correo electrónico se agregaron con éxito a cada buzón.

Running the new email address verification

Enviando Pronóstico del Tiempo Diario a una Lista de Correo

En este ejemplo, se asume que tienes un archivo CSV que contiene una lista de direcciones de correo electrónico de suscriptores y su área o ubicación. Estos suscriptores esperan recibir un correo electrónico diario con el pronóstico del tiempo para el día específico de su ubicación. Observa el ejemplo de CSV a continuación con el nombre de archivo subscribers.csv.

Weather forecast subscribers list

El CSV a continuación contiene solo dos suscriptores. Uno en Los Ángeles y otro en Manila.

El objetivo es crear un script que realice las siguientes acciones:

  • Importar la información de correo electrónico y área desde el archivo subscribers.csv
  • Para cada suscriptor:
    – Descargar la imagen del pronóstico del tiempo según el área del suscriptor desde https://wttr.in/
    – Enviar la imagen del pronóstico del tiempo como correo electrónico a la dirección de correo electrónico del suscriptor.

El siguiente script realiza las acciones mencionadas anteriormente. Solo necesitas modificar las primeras tres variables: $senderAddress, $smtpServer, y $smtpPort. Luego, copia este código y guárdalo como Send-WeatherInfo.ps1. Consulta los comentarios sobre cada sección del script para obtener más información sobre lo que hace el código.

# COMIENZA aquí la configuración de SMTP
$senderAddress = '<SENDER EMAIL ADDRESS HERE'
$smtpServer = '<SMTP RELAY SERVER HERE>'
$smtpPort = 25
# COMIENZA aquí la configuración de SMTP

# Importar la lista de correos electrónicos de los suscriptores
$subscriber_list = Import-Csv .\subscribers.csv

# Obtener el pronóstico del tiempo y enviar correo electrónico
$subscriber_list.foreach(
    {
				
        # Construir URL para obtener información meteorológica basada en el área
        $uri = ('<https://wttr.in/>' + $_.Area + '_u1F.png')
        # Obtener la imagen del pronóstico del tiempo del área. Guardar la imagen como <ÁREA>.png
        $imageFile = (((Resolve-Path .\).Path) + "$($_.Area).png")
        Start-BitsTransfer $uri -Destination $imageFile

        # Crear objeto de adjunto
        $attachment = New-Object System.Net.Mail.Attachment -ArgumentList $imageFile
        $attachment.ContentDisposition.Inline = $true
        $attachment.ContentDisposition.DispositionType = "Inline"
        $attachment.ContentType.MediaType = "image/png"
        $attachment.ContentId = "weatherImage"

        # Componer mensaje
        $emailMessage = New-Object System.Net.Mail.MailMessage
        $emailMessage.From = $senderAddress
        $emailMessage.To.Add($_.Email)
        $emailMessage.Subject = ('Weather Forecast - ' + $_.Area)
        $emailMessage.IsBodyHtml = $true
        $emailMessage.Body = '<img src="cid:weatherImage">'
        $emailMessage.Attachments.Add($attachment)

        # Enviar mensaje
        Write-Output "Sending Weather Info to $($_.Email)"
				$smtp = New-Object Net.Mail.SmtpClient($smtpServer, $smtpPort)
        $smtp.Send($emailMessage)

        # Liberar objetos
        $attachment.Dispose()
        $emailMessage.Dispose()
    }
)

Una vez que se ejecute el script, se enviará un correo electrónico a cada suscriptor similar al ejemplo de captura de pantalla de correo electrónico a continuación.

Weather forecast for Manila sent as an email to the subscriber
Weather forecast for Los Angeles sent as an email to the subscriber

Resumen

No hay límite para las tareas en las que se puede aplicar el bucle Import-Csv y el bucle ForEach. Siempre que la tarea implique una lista con columnas delimitadas, seguro que aprovecharás esta poderosa combinación.

En este artículo, has aprendido cómo un archivo CSV es similar a una base de datos. También has aprendido cómo usar Import-Csv para importar datos y cómo hacer referencia a los valores durante la iteración del bucle ForEach.

I hope that with the many examples provided in this article, you now understand more of the Import-Csv and ForEach. And, that you would be able to use the knowledge you gained in this article in your administration and automation tasks.

Lectura adicional

Source:
https://adamtheautomator.com/import-csv-and-the-foreach-loop/