Domine Import-Csv e Outros Comandos CSV no PowerShell

O cmdlet Export-Csv do PowerShell e os cmdlets Import-Csv do PowerShell permitem aos administradores importar CSVs via loop foreach, usar Export-Csv para anexar CSVs e exportar arrays para um arquivo CSV e muito mais.

Neste artigo, você aprenderá sobre muitos cenários comuns nos quais pode usar o PowerShell para gerenciar CSVs, como:

  • Leitura de Arquivos CSV com PowerShell
  • Salvando Arquivos CSV com PowerShell
  • Formatando Saída Antes de Executar Export-CSV
  • Anexando a um CSV
  • Anexando Diferenças a um Arquivo Existente
  • Export-CSV e a String #TYPE

Se você não está familiarizado com o funcionamento interno dos arquivos CSV, eles são arquivos de texto que seguem um formato padrão de separar literalmente seus valores em uma tabela por vírgulas. Você pode criar um arquivo CSV no PowerShell usando o cmdlet Export-Csv e encaminhando um ou mais objetos para ele.

O comando abaixo encontra os dois primeiros processos em execução e passa os objetos gerados para o cmdlet Export-Csv. O cmdlet Export-Csv então cria um arquivo CSV chamado processes.csv na raiz do seu disco do sistema (provavelmente C:\).

PS51> Get-Process | Select-Object -First 2 | Export-CSV -Path "$env:SystemDrive\processes.csv"

Agora abra o arquivo processes.csv com o bloco de notas. Você deverá ver "Name","SI","Handles","VM" no topo como cabeçalhos. Você também verá #TYPE System.Diagnostics.Process, o que pode não fazer muito sentido agora. Não se preocupe, abordaremos essa string neste artigo.

Lendo Arquivos CSV com Import-Csv

Quer mais dicas como esta? Confira meu blog pessoal do PowerShell.

O PowerShell possui alguns comandos que permitem a leitura de arquivos de texto. Esses comandos são Get-Content e Import-Csv. Tecnicamente, ambos esses cmdlets leem o arquivo da mesma maneira. No entanto, o Import-Csv vai um passo além. Ele compreende a estrutura subjacente não apenas de um arquivo de texto, mas de um arquivo CSV.

Dado que um arquivo CSV segue um determinado esquema, o Import-Csv compreende esse esquema. Este cmdlet não apenas lê o arquivo de texto do disco, mas também converte as linhas no arquivo CSV em objetos do PowerShell.

Arquivos Não CSV

Geralmente, os dados de um CSV são separados por vírgula, mas há momentos em que um CSV (tecnicamente não um CSV nesse ponto) possui dados separados por um delimitador diferente. Esses delimitadores são às vezes uma tabulação ou talvez um ponto e vírgula.

Se você tiver um CSV com um delimitador diferente, você pode usar o parâmetro Delimiter. Este parâmetro informa ao Import-Csv para não procurar por vírgulas, que é o padrão, mas sim por outro valor.

Por exemplo, se você tiver um arquivo separado por tabulação, você pode ler o arquivo da seguinte forma:

PS51> Import-Csv -Path tab-separated-data.csv -Delimiter "`t"

Adicionando Cabeçalhos

A common Import-Csv parameter is Header. This parameter lets you specify the property names of the objects created by this cmdlet.

Por padrão, o cmdlet Import-Csv tratará a primeira linha do arquivo CSV como cabeçalhos. Ele converterá esses valores em propriedades de cada linha (objeto). Mas se você tiver um arquivo CSV sem uma linha de cabeçalho, você pode usar o parâmetro Header para definir um você mesmo.

O parâmetro Header impede que o Import-CSV use sua primeira linha como cabeçalho e também evita que você tenha que abrir manualmente o arquivo CSV para adicionar cabeçalhos.

Para demonstrar esse comportamento, abra o bloco de notas e copie/cole o texto abaixo. Este texto representará um conjunto de dados com três linhas e duas colunas.

a,1
b,2
c,3

Salve o arquivo de texto como test.csv. Não se esqueça de habilitar as extensões de tipo de arquivo ou coloque o arquivo entre aspas duplas para não salvá-lo acidentalmente com a extensão .csv.txt!

Agora, use Import-CSV para ler o arquivo CSV recentemente criado sem o parâmetro Header e inspecione a saída.

PS51> Import-Csv .\test.csv

a 1
---
b 2
c 3

Observe que a primeira linha foi usada como as propriedades do objeto. A e 1 não são “rótulos” que você deseja para as propriedades do objeto. A, b e c são letras enquanto 1, 2 e 3 são números. Você precisa definir esses com o parâmetro Header como abaixo:

PS51> Import-Csv .\test.csv -Header "Letter", "Number"

Letter Number
------ ------
a      1
b      2
c      3

Salvando Arquivos CSV com PowerShell

Se você precisar criar ou salvar um arquivo CSV a partir de objetos PowerShell, também pode fazer o contrário. Enquanto o cmdlet Import-Csv “converte” um arquivo CSV em objetos PowerShell, Export-Csv faz o oposto. Este cmdlet “converte” objetos PowerShell em um arquivo CSV.

Ao salvar um arquivo CSV com Export-Csv, você pode posteriormente visualizar ou usar esses dados em outros sistemas.

Por exemplo, posso salvar todos os processos em execução no meu computador redirecionando Get-Process para o cmdlet Export-Csv.

PS51> Get-Process | Export-Csv -Path processes.csv

O cmdlet Export-Csv é simples por natureza, mas há algumas armadilhas a serem observadas.

Formatando a Saída Antes de Executar o Export-CSV

Como você viu acima, o Export-Csv, por si só, faz uma conversão “bruta”. Ele não adiciona nenhum formato de texto rico especial, não adiciona cores e assim por diante.

Uma das armadilhas mais comuns é tentar tornar a saída mais bonita antes de exportá-la para um CSV. Muitos usuários tentarão melhorar a aparência da saída antes de exportá-la para um CSV. Mas estou prestes a mostrar que isso pode piorar as coisas.

Você pode abrir um CSV no Microsoft Excel e colocar em itálico, negrito, adicionar cores e muitas outras coisas, mas se você salvar o arquivo como um CSV (em vez de uma pasta de trabalho do Excel), toda a formatação será apagada. Um arquivo CSV simplesmente não é “inteligente” o suficiente.

Lembre-se de que os arquivos CSV são apenas arquivos de texto simples com valores delimitados por vírgulas (ou às vezes por tabs). Encaminhar Import-Csv para um Format-* cmdlet do PowerShell não funcionará como esperado.

Conforme a documentação do Microsoft Export-Csv: “Não formate objetos antes de enviá-los ao cmdlet Export-CSV. Se Export-CSV receber objetos formatados, o arquivo CSV conterá as propriedades de formatação em vez das propriedades do objeto.”

Por que isso acontece?

Abrir uma janela do PowerShell e criar alguns dados fictícios. Vamos usar o exemplo Get-Process abordado na primeira seção deste artigo. Mas desta vez, atribua a saída a uma variável. Em seguida, encaminhe esses objetos de processo para o cmdlet Format-Table.

PS51> $a = Get-Process
PS51> $a | Format-Table
Using Format-Table

Você pode ver que, usando Format-Table, agora você tem uma saída tabular limpa.

Agora salve esta saída em outra variável.

PS51> $b = $a | Format-Table

Agora veja as propriedades nos valores das variáveis $a e $b com Get-Member. Este cmdlet ajudará você a entender por que esses dois objetos aparentemente semelhantes não são exportados para um arquivo CSV da mesma maneira:

PS51> $a | Get-Member
System.Diagnostics.Process object type
PS51> $b | Get-Member
Format-Table‘s many object types

O resultado diretamente do Get-Process é: TypeName: System.Diagnostics.Process, enquanto o resultado do Format-Table é completamente diferente. Ele retorna muitos tipos diferentes com propriedades variadas.

Se você visualizar $a e $b no console, a saída parecerá idêntica. Esse comportamento é devido ao sistema de formatação do PowerShell.

Como isso afeta a saída do Export-Csv?

PS51> $b | Export-Csv | Format-Table

Export-Csv lê cada objeto como está. Quando você envia a saída para um cmdlet Format-*, você está alterando a entrada que o Export-CSV recebe. Isso afeta a saída que é salva no seu novo arquivo CSV.

Se você estiver enviando a saída para o cmdlet Export-Csv, não envie a saída para nenhum cmdlet Format-*.

Lembre-se de que os CSVs são focados em dados, não em formatação.

Adicionar a um arquivo CSV existente

Às vezes, você pode ter um arquivo existente ao qual deseja adicionar dados em vez de criar um novo completamente. Por padrão, Export-Csv sobrescreverá qualquer arquivo especificado pelo parâmetro Path.

Se você precisar adicionar dados a um CSV, use o parâmetro Append.

Vamos supor que você tenha um loop no qual deseja salvar cada objeto processado em um arquivo CSV. Para cada iteração, você tem um objeto diferente que gostaria de salvar no arquivo CSV. Como você está chamando repetidamente o Export-Csv, ele irá sobrescrever o arquivo CSV se você não usar o parâmetro Append. Sem o parâmetro Append, você obterá apenas o último objeto, o que na maioria dos casos não é a saída desejada.

O exemplo abaixo está buscando os cinco primeiros processos em execução. Em seguida, ele entra em um loop foreach do PowerShell usando o Import-Csv e registra as propriedades Name e ProductVersion no arquivo test.csv um de cada vez.

Get-Process | Select-Object -First 5 | Foreach-Object {
    $_ | Select-Object Name, ProductVersion | Export-CSV -Path C:\test.csv -Append
}

Sem o uso do parâmetro Append, você verá que apenas o quinto processo será exibido no arquivo CSV.

Anexando Diferenças a um arquivo CSV

É possível apenas anexar diferenças de propriedades a um arquivo CSV existente com o Export-Csv. Isso significa que se as colunas de uma linha CSV e o objeto a ser registrado forem diferentes, então vá em frente e anexe-os.

Para apenas anexar diferenças ao arquivo CSV, você precisará usar os parâmetros Append e Force juntos. De acordo com a documentação da Microsoft, “quando os parâmetros Force e Append são combinados, objetos que contêm propriedades incompatíveis podem ser gravados em um arquivo CSV. Apenas as propriedades que correspondem são gravadas no arquivo. As propriedades incompatíveis são descartadas.”

Para demonstrar, crie um objeto com duas propriedades; Nome e Idade.

PS51> $Content = [PSCustomObject]@{Name = "Johnny"; Age = "18"}

Agora crie outro objeto com uma propriedade Nome e CEP.

PS51> $OtherContent = [PSCustomObject]@{Name = "Joe"; Zip = "02195"}

Cada objeto tem propriedades diferentes.

Em seguida, crie um arquivo CSV a partir do primeiro objeto e tente adicionar o segundo objeto ao CSV sem o parâmetro Force. Você receberá um erro.

PS51> $Content | Export-CSV -Path .\User.csv -NoTypeInformation
PS51> $OtherContent | Export-CSV -Path .\User.csv -NoTypeInformation -Append
Export-Csv without Force

No entanto, se você usar o parâmetro Force, Export-Csv funcionará muito bem.

PS51> $OtherContent | Export-CSV -Path .\User.csv -NoTypeInformation -Append -Force

No entanto, você notará que a coluna CEP desapareceu no arquivo CSV. Use o Force com cuidado. Pode não fornecer a saída pretendida.

PS51> Import-Csv -Path .\User.csv

Name   Age
----   ---
Johnny 18
Joe

Export-CSV e a String #TYPE

Por padrão, ao usar Export-CSV sem parâmetros adicionais, incluirá uma string #TYPE no topo do seu arquivo CSV. Esta string é seguida pelo tipo de objeto que Export-Csv recebeu.

#TYPE System.Diagnostics.Process

Na maioria das vezes, esta string na verdade não é útil ao consumir a saída. Esta string está lá apenas no caso de você precisar manter o tipo de objeto de onde vieram as propriedades e valores.

Para remover esta string, use o parâmetro NoTypeInformation. Este parâmetro remove esta string do CSV completamente.

Observe que a partir do PowerShell Core, isso não é mais necessário.

Resumo

Usando os cmdlets Import-CSV e Export-CSV do PowerShell, você pode trabalhar facilmente com arquivos CSV. Esses são dois cmdlets úteis que você deve usar com frequência ao lidar com objetos e arquivos CSV.

Minha esperança é que, com as explicações e exemplos que apresentei aqui, você possa ter uma compreensão clara das situações em que pode aproveitar esses cmdlets em seu benefício.

Quer mais dicas como essa? Confira o meu blog pessoal sobre PowerShell.

Source:
https://adamtheautomator.com/import-csv/