Processar Dados CSV com Import-Csv e Loop ForEach no PowerShell

Você já teve que fazer a mesma tarefa várias vezes? Tipo, criando múltiplos usuários do Active Directory um por vez usando a interface gráfica? Ou que tal fazer login em um servidor para excluir logs antigos de algumas pastas selecionadas? Se sua resposta for sim, saiba que você não está sozinho. É hora de dominar o Import-Csv do PowerShell e o loop foreach.

Não há nada de errado com tarefas manuais; às vezes é necessário. Mas quando se trata de ler e processar arquivos CSV, o cmdlet PowerShell Import-Csv e o loop ForEach podem ajudar.

O cmdlet Import-Csv do PowerShell é uma excelente maneira de ler dados de uma fonte tabulada, como um arquivo CSV. Você pode usar o loop ForEach para iterar sobre cada linha nos dados do CSV.

Neste artigo, você aprenderá como usar essa poderosa combinação para automatizar tarefas em massa, mundanas e repetitivas.

Se você é novo no cmdlet Import-Csv e no loop ForEach, ou se quiser revisar o que já sabe, você pode visitar esses links para aprender mais.

Gerenciando arquivos CSV no PowerShell com Import-Csv (loop foreach)

Voltando ao básico: O loop foreach do PowerShell

Pré-requisitos

Há vários exemplos e demonstrações neste artigo. Para acompanhar, você precisará de algumas coisas primeiro.

  • A script editor such as Visual Studio Code, Atom, or Notepad++. Use whichever one you’re comfortable with.
  • Windows PowerShell 5.1 ou PowerShell Core 6+
  • Acesso ao Exchange Online (opcional se você seguir o exemplo prático relacionado ao Exchange Online).

Colocando Import-Csv e o loop ForEach em Ação

Nas próximas seções, há vários exemplos de como usar o cmdlet Import-Csv e o loop ForEach que você pode encontrar em cenários do mundo real. Embora esses exemplos de PowerShell de importação CSV foreach sejam específicos para cada propósito, é crucial entender que o conceito e a técnica empregados são os mesmos.

Lendo e Exibindo Registros de um CSV

Talvez o uso mais básico de Import-Csv e loop ForEach seja ler registros de um arquivo e exibi-los no console. A anatomia de um arquivo CSV é semelhante à de um banco de dados. Ele possui cabeçalhos de coluna, e cada linha é considerada um registro.

Por exemplo, abaixo está o conteúdo do arquivo chamado employee.csv, que consiste em três colunas – EmployeeID, Nome, e Aniversário, e quatro registros.

CSV containing employee records

O código abaixo importa o conteúdo do arquivo employee.csv e, em seguida, direciona os dados importados para o cmdlet ForEach-Object. Então, ForEach-Object percorrerá cada registro no CSV importado para exibir os valores concatenados no console. Copie o código abaixo e salve-o como list-employee.ps1.

Nota: O tipo de loop ForEach usado neste exemplo abaixo é o cmdlet ForEach-Object. Consulte a seção “O cmdlet ForEach-Object” neste artigo.

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

Assim que o script for salvo, execute-o chamando seu nome de arquivo no PowerShell. Quando o script for executado, você deverá ver uma saída semelhante à captura de tela abaixo.

Imported CSV records displayed in the console

Pesquisando e Exibindo Registros de um CSV

No exemplo anterior, você aprendeu como ler e exibir todos os registros de um CSV. Neste exemplo, o mesmo arquivo CSV employee.csv será usado, mas desta vez, você criará uma função PowerShell para procurar um EmployeeID no CSV.

O trecho de código abaixo é uma função PowerShell chamada Find-Employee que possui apenas um parâmetro. O nome do parâmetro é EmployeeID e ele aceita um valor de ID de funcionário a ser pesquisado no CSV.

Antes que esta função possa ser usada, ela precisa ser importada para sua sessão do PowerShell primeiro. Existem duas maneiras de importar a função Find-Employee para a memória:

  1. Copiando e colando o código abaixo no PowerShell.
  2. Salvando o script como Find-Employee.ps1 e importando-o usando a técnica dot-sourcing.

Observação: O tipo de loop ForEach usado neste exemplo abaixo é o comando ForEach. Consulte a seção “O comando foreach” em este artigo.

Function Find-Employee {
    param (
        # O parâmetro aceita o ID do funcionário a ser pesquisado.
        [Parameter(Mandatory)]
        $EmployeeID
    )

    # Importe o conteúdo do arquivo employee.csv e armazene-o na variável $employee_list.
    $employee_list = Import-Csv .\employee.csv

    # Percorra todos os registros no CSV
    foreach ($employee in $employee_list) {

        # Verifique se o ID do funcionário do registro atual é igual ao valor do parâmetro EmployeeID.
        if ($employee.EmployeeID -eq $EmployeeID) {

            # Se o EmployeeID for encontrado, exiba o registro no console.
            Write-Host "$($employee.Name), whose Employee ID is $($employee.EmployeeID), was born on $($employee.Birthday)."
        }
    }
}

Assim que o código da função for importado na sessão do PowerShell, chame digitando o nome da função conforme abaixo.

Find-Employee

Ao executar a função sem usar o parâmetro EmployeeID, será solicitado o valor do EmployeeID a ser pesquisado. Veja o exemplo de saída abaixo.

Function to search a CSV file for a specific record

Ou, a função pode ser executada com o valor do parâmetro EmployeeID especificado durante a execução, como mostrado abaixo.

Find-Employee -EmployeeID 'E-2023'

Obtendo o Uso do Espaço em Disco de Múltiplos Servidores

Uma tarefa rotineira comum entre os administradores de sistema é monitorar o uso do espaço em disco de vários servidores. Em vez de fazer login em cada servidor para verificar o uso do espaço em disco, você pode criar uma lista CSV contendo nomes de servidores, letras de unidade e limites. Em seguida, usando o PowerShell, importe o arquivo CSV e percorra cada linha para executar uma consulta.

Para criar um script que obtém o uso do espaço em disco de servidores remotos, primeiro crie a lista CSV com os seguintes cabeçalhos:

  • servername – este é o nome do servidor a ser consultado.
  • disk – esta é a letra da unidade cujo uso de espaço será recuperado.
  • threshold – isso define o limite em GB. Se o espaço livre do disco for inferior a esse valor, o relatório mostrará um status de aviso.

O exemplo abaixo mostra que existem quatro registros listados. Seu arquivo CSV será diferente dependendo do número de servidores ou discos a serem lidos.

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

Depois que o CSV estiver finalizado, salve o arquivo como servers.csv. Isso servirá como a lista de entrada que será importada pelo script PowerShell.

Para fornecer um exemplo de obtenção do uso do espaço em disco, copie o código abaixo para o seu editor de script e salve-o como diskReport.ps1. O script deve ser salvo no mesmo local que o caminho do 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'
            }
        }
    }
}

O script acima realiza as seguintes ações quando é executado.

  • Importa o arquivo csv chamado servers.csv e o armazena na variável $server_list.
  • Itera pela lista de servidores armazenada na variável $server_list.
  • Em cada iteração do loop foreach, a linha atual é representada pela variável $server.
  • Obtém as informações do disco dos servidores usando o cmdlet Get-WmiObject.
  • Selecione apenas as propriedades relevantes para exibir.
    Nome do Servidor – Este é o nome do sistema que está sendo consultado.
    Letra do Disco – A letra atribuída à unidade.
    Tamanho (GB) – O tamanho do disco em GB
    Livre (GB) – O espaço livre em GB
    Limiar (GB) – O limiar definido em GB
    Status – Se o valor Livre (GB) for menor que o valor Limiar (GB), o status retornado será ‘Aviso’. Caso contrário, o status será ‘Normal’

Após salvar o arquivo de script diskReport.ps1, ele está pronto para ser executado chamando seu nome no PowerShell.

./diskReport.ps1

Uma vez executado, a captura de tela abaixo mostra a saída do script.

Disk space information gathered from multiple servers

A saída também pode ser exportada para CSV. Exportar para CSV é útil quando o relatório precisa ser compartilhado, pois o arquivo CSV exportado pode ser enviado por e-mail ou enviado para um compartilhamento de arquivos ou para um site do SharePoint. Certifique-se de verificar Exportar para CSV: a maneira do PowerShell de tratar arquivos CSV como cidadãos de primeira classe se você deseja obter mais informações sobre a exportação para CSV.

Criando Múltiplos Usuários do Active Directory

Neste ponto, você já teria uma ideia sólida sobre como usar Import-Csv e ForEach. Este próximo exemplo leva seu aprendizado um pouco mais adiante, adicionando os cmdlets New-ADUser e Get-ADUser à mistura.

Vamos supor que você tenha recebido um arquivo CSV `new_employees.csv` contendo a lista de novos funcionários do departamento de RH. Cada linha no arquivo CSV representa um usuário a ser integrado e possui as seguintes colunas: FirstName, LastName, Department, State, EmployeeID e Office.

O nome de usuário deve ser derivado da primeira letra do nome do funcionário concatenada com o sobrenome (por exemplo, bparr para o usuário Bob Parr).

CSV file containing new employees information for on-boarding

Depois que o arquivo CSV for salvo, o script abaixo usa `Import-Csv` para ler o arquivo CSV new_employees.csv. Em seguida, itera através de cada linha, passando os valores para os parâmetros apropriados 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
}

Após a execução do script, os novos usuários já devem existir no Active Directory. No entanto, é uma boa prática confirmar se as contas de usuário foram realmente criadas.

Usando o mesmo arquivo CSV new_employees.csv como referência, o script abaixo irá executar a importação CSV e foreach para obter os objetos ADUser que correspondem aos da lista.

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

Adicionando um Endereço de Email Proxy à Caixa de Correio do Office 365

No gerenciamento de caixas de correio do Office 365, solicitações para adicionar endereços proxy para vários usuários não são incomuns. Comumente, nesse tipo de solicitação, o administrador recebe uma lista de usuários e o endereço de e-mail a ser adicionado, similar ao exemplo CSV abaixo.

The new_address.csv file contents

Nota: Antes de poder executar qualquer cmdlet do Exchange Online no PowerShell, você deve estar conectado primeiro ao shell de Gerenciamento do Exchange Online.

Usando os cmdlets Import-Csv e ForEach em um script do PowerShell, a lista pode ser processada de uma só vez. O script abaixo mostra como isso pode ser feito.

O script abaixo importa o conteúdo do arquivo new_address.csv e o armazena na variável $user_list. Em seguida, usando o método foreach(), o PowerShell percorre toda a lista de usuários e utiliza os valores username e email em cada registro para adicionar um novo endereço de e-mail a cada caixa de correio.

$user_list = Import-Csv .\new_address.csv

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

Depois que o script é executado, não haverá nenhuma saída exibida no console. Nenhuma saída na tela significa que o novo endereço de e-mail foi adicionado com sucesso. Mas, como garantir que os endereços de e-mail foram adicionados?

Usando o mesmo arquivo CSV new_address.csv como referência, é possível verificar se os novos endereços foram adicionados usando Import-Csv e ForEach.

O script abaixo importa o conteúdo do arquivo new_address.csv e o armazena na variável $user_list. Em seguida, usando o método foreach(), o PowerShell percorre toda a lista de usuários para verificar se o novo endereço de e-mail existe na lista de endereços de proxy da caixa de correio. Se encontrado, o status retornará True; caso contrário, o 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"
        }
    }
)

Quando o script de validação é executado, a saída deve se parecer com a mostrada na captura de tela abaixo. Você notará na saída abaixo que o status é todo TRUE, o que significaria que os novos endereços de e-mail foram adicionados com sucesso a cada caixa de correio.

Running the new email address verification

Enviando Previsão Diária do Tempo para uma Lista de E-mails

Neste exemplo, presume-se que você tenha um arquivo CSV contendo uma lista de endereços de e-mail dos assinantes e sua área ou localização. Esses assinantes estão esperando um e-mail diário contendo a previsão do tempo para o dia específico de sua localização. Observe o CSV de exemplo abaixo com o nome de arquivo subscribers.csv.

Weather forecast subscribers list

O CSV abaixo contém apenas dois assinantes. Um em Los Angeles e outro em Manila.

O objetivo é criar um script que execute as seguintes ações:

  • Importar as informações de e-mail e área do arquivo subscribers.csv
  • Para cada assinante:
    – Baixar a imagem da previsão do tempo com base na área do assinante em https://wttr.in/
    – Enviar a imagem da previsão do tempo por e-mail para o endereço de e-mail do assinante.

O script abaixo realiza as ações listadas acima. Você só precisa modificar as três primeiras variáveis – $senderAddress, $smtpServer, e $smtpPort. Em seguida, copie este código e salve como Send-WeatherInfo.ps1. Consulte os comentários acima de cada seção do script para saber mais sobre o que o código faz.

# COMECE aqui as configurações do SMTP
$senderAddress = '<SENDER EMAIL ADDRESS HERE'
$smtpServer = '<SMTP RELAY SERVER HERE>'
$smtpPort = 25
# COMECE aqui as configurações do SMTP

# Importe a lista de e-mails dos assinantes
$subscriber_list = Import-Csv .\subscribers.csv

# Obtenha a previsão do tempo e envie por e-mail
$subscriber_list.foreach(
    {
				
        # Construa o URL para informações meteorológicas com base na área
        $uri = ('<https://wttr.in/>' + $_.Area + '_u1F.png')
        # Obtenha a imagem da previsão do tempo da área. Salve a imagem como <AREA>.png
        $imageFile = (((Resolve-Path .\).Path) + "$($_.Area).png")
        Start-BitsTransfer $uri -Destination $imageFile

        # Crie o objeto de anexo
        $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"

        # Componha a mensagem
        $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)

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

        # Descarte os objetos
        $attachment.Dispose()
        $emailMessage.Dispose()
    }
)

Depois que o script é executado, um e-mail será enviado para cada assinante, semelhante ao exemplo de captura de tela de e-mail abaixo.

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

Resumo

Não há limite para as tarefas onde o Import-Csv e o loop ForEach podem ser aplicados. Desde que a tarefa envolva uma lista com colunas delimitadas, você certamente vai se aprofundar nessa poderosa combinação.

Neste artigo, você aprendeu como um arquivo CSV é semelhante a um banco de dados. Você também aprendeu como usar Import-Csv para importar dados e como referenciar os valores durante a iteração do loop 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.

Leitura adicional

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