Domine Import-Csv e Outros Comandos CSV no PowerShell

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

Neste artigo, você aprenderá sobre muitos cenários comuns em que 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 de arquivos CSV, eles são arquivos de texto que seguem um formato padrão de separar literalmente vírgulas entre seus valores em uma tabela. 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 da unidade do seu 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ê deve ver "Name","SI","Handles","VM" no topo como cabeçalhos. Você também verá #TYPE System.Diagnostics.Process, que pode não fazer muito sentido agora. Não se preocupe, vamos abordar essa string neste artigo.

Lendo Arquivos CSV com Import-Csv

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

O PowerShell tem alguns comandos que permitem ler arquivos de texto. Esses comandos são Get-Content e Import-Csv. Cada um desses dois cmdlets lê tecnicamente o arquivo da mesma maneira. Mas Import-Csv vai um passo além. Import-Csv entende a estrutura subjacente não apenas de um arquivo de texto, mas de um arquivo CSV.

Como um arquivo CSV segue um determinado esquema, Import-Csv compreende o esquema CSV. 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

Normalmente, os dados de um CSV são separados por vírgula, mas há momentos em que um CSV (não tecnicamente um CSV naquele ponto) tem dados separados por um delimitador diferente. Esses delimitadores às vezes são um tab 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 diz ao Import-Csv para não procurar por vírgulas, o que faz por padrão, mas por outro valor.

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

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 linha superior do arquivo CSV como cabeçalhos. Ele então converte esses valores em propriedades de cada linha (objeto). Mas se você tiver um arquivo CSV que não tenha 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 seu cabeçalho e também evita que você tenha que abrir manualmente o arquivo CSV para adicionar cabeçalhos você mesmo.

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 colocar o arquivo entre aspas duplas para que você não acidentalmente o salve como um arquivo com final .csv.txt!

Agora, use o Import-CSV para ler o arquivo CSV recém-criado sem o parâmetro Header e inspecionar a saída.

PS51> Import-Csv .\test.csv

a 1
---
b 2
c 3

Repare que ele usou a primeira linha como as propriedades do objeto. A e 1 não são “rótulos” que você quer 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 o PowerShell

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

Ao salvar um arquivo CSV com Export-Csv permite que você mais tarde visualize ou use esses dados em outros sistemas.

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

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

O cmdlet Export-Csv é simples por natureza, mas existem algumas armadilhas para ficar de olho.

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

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

Uma das armadilhas mais comuns é tentar deixar a saída bonita antes de exportá-la para um CSV. Muitos usuários tentarão deixar a saída melhor antes de exportá-la para um CSV. Mas estou prestes a mostrar que isso piora as coisas.

Você pode abrir um arquivo CSV no Microsoft Excel e colocar em itálico, negrito, adicionar cores e muitas outras coisas, mas se salvar o arquivo como CSV (em vez de um livro 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 abas). A canalização do Import-Csv para um cmdlet PowerShell Format-* não funcionará como esperado.

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

Por quê?

Abra uma janela do PowerShell e crie 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ê verá que, ao usar Format-Table, agora tem uma saída limpa e tabular.

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

PS51> $b = $a | Format-Table

Agora, visualize as propriedades tanto nas variáveis $a quanto $b com Get-Member. Este cmdlet ajudará 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

A saída diretamente de Get-Process retorna: TypeName: System.Diagnostics.Process, enquanto a saída de Format-Table é completamente diferente. Ela 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 de Export-Csv?

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

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

Se você vai direcionar a saída para o cmdlet Export-Csv, não direcione a saída para nenhum cmdlet Format-*.

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

Anexando a um Arquivo CSV

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

Se você precisa anexar 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 em um arquivo CSV. Como você está chamando repetidamente o Export-Csv, ele 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á encontrando os primeiros cinco processos em execução. Em seguida, ele entra em um loop foreach do PowerShell usando 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 usar o parâmetro Append, você verá que apenas o quinto processo será exibido no arquivo CSV.

Adicionando Diferenças a um Arquivo CSV

É possível adicionar apenas as diferenças de propriedade a um arquivo CSV existente com Export-Csv. Isso significa que se as colunas de uma linha CSV e o objeto a ser registrado forem diferentes, você pode adicioná-los.

Para adicionar apenas as 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. Somente as propriedades que coincidem são gravadas no arquivo. As propriedades incompatíveis são descartadas.”

Para demonstrar, crie um objeto com duas propriedades; Name e Age.

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

Agora, crie outro objeto com uma propriedade Name e Zip.

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

Cada objeto possui propriedades diferentes.

Em seguida, crie um arquivo CSV a partir do primeiro objeto e tente anexar 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á perfeitamente.

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

No entanto, você notará que a coluna Zip 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, usar Export-CSV sem parâmetros adicionais incluirá uma string #TYPE no topo do seu arquivo CSV. Essa string é seguida pelo tipo de objeto que Export-Csv recebeu.

#TYPE System.Diagnostics.Process

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

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

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ê consiga entender claramente as situações em que pode aproveitar esses cmdlets em seu benefício.

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

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