Trabalhando com CSV
Esta aula aborda o trabalho com arquivos CSV no PowerShell, ensinando a importar e exportar dados usando os cmdlets Import-Csv e Export-Csv, manipulando objetos resultantes, lidando com delimitadores personalizados e explorando casos de uso práticos. Ao final, você será capaz de integrar CSV em seus scripts de automação e análise de dados.
O formato CSV (Comma-Separated Values) é um dos formatos de dados mais comuns e simples para troca de informações entre sistemas. No PowerShell, trabalhar com CSV é uma tarefa cotidiana, seja para exportar resultados de comandos, importar dados de fontes externas ou configurar scripts. Dominar os cmdlets Import-Csv e Export-Csv é essencial para qualquer profissional que deseja automatizar tarefas administrativas ou processar dados de forma eficiente.
Nesta aula, vamos explorar profundamente como o PowerShell lida com CSV, desde a importação e exportação até a manipulação de objetos criados a partir desses arquivos. Também veremos como lidar com delimitadores diferentes e discutiremos casos de uso comuns, com exemplos práticos que você pode aplicar imediatamente em seus scripts.
Import-Csv e Export-Csv
Os cmdlets Import-Csv e Export-Csv são as ferramentas primárias para trabalhar com arquivos CSV no PowerShell. Eles convertem entre arquivos de texto estruturado e objetos do PowerShell, permitindo que você use a pipeline para processar dados de forma consistente.
O Export-Csv converte objetos em linhas de um arquivo CSV, enquanto o Import-Csv faz o caminho inverso, criando objetos a partir das linhas do arquivo. Esses cmdlets são simétricos e poderosos, mas é importante entender suas nuances para evitar armadilhas comuns, como a perda de tipos de dados (tudo vira string).
Exemplo básico de exportação:
$servidores = @(
[PSCustomObject]@{ Nome = 'WEB01'; IP = '192.168.1.10'; Sistema = 'Windows Server 2022' },
[PSCustomObject]@{ Nome = 'DB01'; IP = '192.168.1.11'; Sistema = 'Windows Server 2022' },
[PSCustomObject]@{ Nome = 'FW01'; IP = '192.168.1.1'; Sistema = 'PFSense' }
)
$servidores | Export-Csv -Path .\servidores.csv -NoTypeInformation
Get-Content .\servidores.csvNesse exemplo, criamos uma lista de objetos com propriedades Nome, IP e Sistema, exportamos para servidores.csv e exibimos o conteúdo do arquivo. O parâmetro -NoTypeInformation evita que a linha com o tipo de objeto seja incluída, deixando o CSV mais limpo.
Agora, importando de volta:
$dadosImportados = Import-Csv .\servidores.csv
$dadosImportados | Format-Table -AutoSizeO resultado é uma coleção de objetos PSCustomObject, cada um com as propriedades Nome, IP e Sistema, todas como strings. Isso permite filtrar, ordenar e manipular os dados facilmente.
Objetos a partir de CSV
Quando você importa um CSV, o PowerShell cria objetos do tipo PSCustomObject (ou PSObject) para cada linha. As colunas viram propriedades e os valores são armazenados como strings. Isso é fundamental: qualquer operação que dependa de tipos (como números ou datas) exigirá conversão explícita.
Exemplo de manipulação de objetos importados:
$csv = Import-Csv .\servidores.csv
# Filtrar servidores Windows
$windows = $csv | Where-Object { $_.Sistema -like '*Windows*' }
$windows | Select-Object Nome, IP
# Converter IP para [System.Net.IPAddress] (apenas demonstração)
$primeiroIP = $csv[0].IP
$ipConvertido = [System.Net.IPAddress]::Parse($primeiroIP)
$ipConvertido.GetType().FullNameRepare que, ao importar, o valor de IP é uma string, e se precisarmos tratá-lo como um endereço IP, devemos convertê-lo manualmente. Isso é comum quando o CSV contém números, datas ou outros tipos não textuais.
Uma técnica útil é usar o parâmetro -Header no Import-Csv quando o arquivo não possui cabeçalho, permitindo que você defina nomes de propriedades personalizados. Veja:
# Arquivo sem cabeçalho: "WEB01,192.168.1.10,Windows"
$dados = Import-Csv .\servidores_sem_header.csv -Header Nome, IP, Sistema
$dados | Format-Table -AutoSizeIsso é muito útil ao lidar com arquivos de sistemas legados que não incluem cabeçalho.
Delimitadores
O padrão do CSV é usar vírgula como delimitador, mas muitos sistemas usam ponto e vírgula (principalmente em regiões onde a vírgula é usada como separador decimal) ou tabulações. O PowerShell permite especificar qualquer delimitador com o parâmetro -Delimiter.
Exemplo com ponto e vírgula:
# Criando um CSV com ponto e vírgula
$dados = @([PSCustomObject]@{ Nome = 'A'; Valor = '10,5' })
$dados | Export-Csv -Path .\dados.csv -Delimiter ';' -NoTypeInformation
# Ver conteúdo
Get-Content .\dados.csv
# Importar corretamente
$importado = Import-Csv .\dados.csv -Delimiter ';'
$importado.Valor # Retorna "10,5" como stringSe você tentar importar um arquivo com ponto e vírgula sem especificar o delimitador, o PowerShell interpretará cada linha como uma única coluna, o que pode causar erros. Portanto, sempre verifique o delimitador do arquivo que está manipulando.
Também é possível usar tabulações como delimitador, útil ao copiar dados de planilhas. O caractere de tabulação pode ser passado usando "`t" (tique invertido + t).
$dados | Export-Csv -Path .\dados_tab.txt -Delimiter "`t" -NoTypeInformation
$importadoTab = Import-Csv .\dados_tab.txt -Delimiter "`t"Casos de uso
Os casos de uso para CSV no PowerShell são vastos. Vamos explorar alguns cenários práticos que você encontrará no dia a dia.
1. Exportação de relatórios: você pode exportar o resultado de qualquer comando que produza objetos para CSV, gerando relatórios que podem ser abertos no Excel ou processados por outras ferramentas.
Get-Process | Export-Csv -Path .\processos.csv -NoTypeInformation2. Importação de listas para automação: se você tem uma lista de usuários, computadores ou qualquer recurso em CSV, pode importá-la e usá-la em loop para executar ações em massa.
$usuarios = Import-Csv .\usuarios.csv
foreach ($usuario in $usuarios) {
# Supondo que o CSV tenha colunas: Nome, Email, Departamento
New-ADUser -Name $usuario.Nome -EmailAddress $usuario.Email -Department $usuario.Departamento
}3. Configuração de servidores: arquivos CSV podem armazenar configurações de máquinas, como IPs, hostnames e funções, permitindo que scripts provisionem infraestrutura de forma declarativa.
$configs = Import-Csv .\config_servidores.csv
foreach ($config in $configs) {
# Chamar função de provisionamento
Provisionar-Servidor -Nome $config.Nome -IP $config.IP -Role $config.Role
}4. Análise de dados: depois de importar, você pode usar cmdlets como Group-Object, Measure-Object e Sort-Object para analisar dados.
$vendas = Import-Csv .\vendas.csv
$vendas | Group-Object Produto | Select-Object Name, Count, @{N='Total';E={($_.Group | Measure-Object -Property Valor -Sum).Sum}}5. Intercâmbio com APIs: muitos serviços web exportam dados em CSV; você pode baixar e processar esses arquivos diretamente no PowerShell.
Invoke-WebRequest -Uri 'https://exemplo.com/dados.csv' -OutFile .\dados.csv
$dados = Import-Csv .\dados.csvBoas práticas e observações finais
Ao trabalhar com CSV no PowerShell, lembre-se de:
- Sempre usar
-NoTypeInformationnoExport-Csvpara evitar a linha extra que pode atrapalhar outros sistemas. - Verificar o delimitador antes de importar; use
Get-Contentpara inspecionar o arquivo. - Lembre-se de que tudo é string após a importação; converta tipos quando necessário.
- Para arquivos grandes, considere usar
Import-Csvcom-Delimitere processamento em pipeline para não sobrecarregar a memória. - Utilize o parâmetro
-Encodingpara garantir a codificação correta (UTF-8, por exemplo) ao exportar/importar com caracteres especiais.
Com essas técnicas, você pode integrar CSV em seus scripts de forma robusta e eficiente, tornando seu trabalho mais produtivo.
Referências
- Documentação oficial do Import-Csv
- Documentação oficial do Export-Csv
- Trabalhando com arquivos CSV no PowerShell (Microsoft Learn)
- CSV na Wikipédia
- Sobre funções e scripts (contexto)
- Exemplos de scripts de administração
Exercícios
Crie um script que exporte a lista de processos em execução no seu sistema para um arquivo chamado
processos.csvusandoExport-Csve depois importe-o novamente, exibindo os 5 primeiros processos com maior uso de memória (WorkingSet).✓ Resposta:# Exportar processos Get-Process | Export-Csv -Path .\processos.csv -NoTypeInformation # Importar e ordenar por WorkingSet (memória em bytes) $processos = Import-Csv .\processos.csv $processos | Sort-Object {[int64]$_.WorkingSet} -Descending | Select-Object -First 5 | Format-Table Name, WorkingSetDado um arquivo CSV com delimitador ponto e vírgula e sem cabeçalho, com colunas: Nome, Idade, Cidade. Escreva um script que importe esse arquivo usando cabeçalho personalizado e exiba apenas as pessoas com idade maior que 30 anos.
✓ Resposta:$pessoas = Import-Csv .\pessoas.csv -Delimiter ';' -Header Nome, Idade, Cidade $pessoas | Where-Object { [int]$_.Idade -gt 30 } | Format-Table Nome, Idade, CidadeExplique por que, ao importar um CSV, todos os valores são tratados como strings e como você pode converter uma coluna para número inteiro em uma expressão de pipeline. Dê um exemplo prático.
✓ Resposta: O PowerShell não tem como inferir o tipo dos dados em um CSV, pois o formato é textual. Por isso, cada valor é lido como string. Para converter, você pode usar o operador de cast ou métodos como[int]. Exemplo:$csv | ForEach-Object { $_.Idade = [int]$_.Idade }ou usar uma propriedade calculada emSelect-Object:$csv | Select-Object Nome, @{N='Idade';E={[int]$_.Idade}}.Crie um script que leia um arquivo CSV de vendas com colunas Produto, Quantidade e PrecoUnitario (separados por vírgula), calcule o total de cada produto (Quantidade * PrecoUnitario) e exporte um novo CSV com as colunas Produto e Total.
✓ Resposta:$vendas = Import-Csv .\vendas.csv $resultado = $vendas | ForEach-Object { [PSCustomObject]@{ Produto = $_.Produto Total = [double]$_.Quantidade * [double]$_.PrecoUnitario } } $resultado | Export-Csv -Path .\totais.csv -NoTypeInformationEscreva um script que importe um CSV com colunas Nome e Email e, para cada linha, envie um e-mail usando o cmdlet
Send-MailMessage(ouSend-MailkitMessagese disponível). Assuma que você tem um servidor SMTP fictício. Não execute de fato; apenas mostre a estrutura.✓ Resposta:$destinatarios = Import-Csv .\contatos.csv foreach ($dest in $destinatarios) { $params = @{ From = 'remetente@exemplo.com' To = $dest.Email Subject = 'Assunto do e-mail' Body = "Olá $($dest.Nome), este é um teste." SmtpServer = 'smtp.exemplo.com' } Send-MailMessage @params }