Master Import-Csv y Otros Comandos CSV en PowerShell

El cmdlet Export-Csv de PowerShell y los cmdlets Import-Csv de PowerShell permiten a los administradores importar archivos CSV mediante un bucle foreach, utilizar Export-Csv para agregar CSV y exportar matrices a un archivo CSV y mucho más.

En este artículo aprenderás sobre muchos escenarios comunes en los que puedes utilizar PowerShell para gestionar archivos CSV, como:

  • Lectura de archivos CSV con PowerShell
  • Guardado de archivos CSV con PowerShell
  • Formato de salida antes de ejecutar Export-CSV
  • Agregando a un CSV
  • Agregando diferencias a un archivo existente
  • Export-CSV y la cadena #TYPE

Si no estás familiarizado con el funcionamiento interno de los archivos CSV, son archivos de texto que siguen un formato estándar de separación de valores con comas en una tabla literalmente. Puedes crear un archivo CSV en PowerShell utilizando el cmdlet Export-Csv y dirigiendo uno o más objetos hacia él.

El siguiente comando encuentra los dos primeros procesos en ejecución y pasa los objetos generados al cmdlet Export-Csv. Luego, el cmdlet Export-Csv crea un archivo CSV llamado processes.csv en la raíz de la unidad del sistema (probablemente C:\).

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

Ahora abre processes.csv con el bloc de notas. Deberías ver "Name","SI","Handles","VM" en la parte superior como encabezados. También verás #TYPE System.Diagnostics.Process, lo cual puede que no tenga mucho sentido ahora. No te preocupes, cubriremos esa cadena en este artículo.

Lectura de Archivos CSV con Import-Csv

¿Quieres más consejos como este? Echa un vistazo a mi blog personal de PowerShell.

PowerShell tiene un par de comandos que te permiten leer archivos de texto. Esos comandos son Get-Content e Import-Csv. Técnicamente, cada uno de estos dos cmdlets lee el archivo de la misma manera. Pero Import-Csv va un paso más allá. Import-Csv comprende la estructura subyacente no solo de un archivo de texto, sino de un archivo CSV.

Dado que un archivo CSV sigue un cierto esquema, Import-Csv entiende el esquema CSV. Este cmdlet no solo lee el archivo de texto del disco, sino que también convierte las filas en el archivo CSV en objetos de PowerShell.

Archivos que no son CSV

Normalmente, los datos de un CSV están separados por coma, pero hay momentos en los que un CSV (técnicamente no un CSV en ese punto) tiene datos separados con un delimitador diferente. A veces esos delimitadores son una tabulación o tal vez un punto y coma.

Si tiene un CSV con un delimitador diferente, puede usar el parámetro Delimiter. Este parámetro indica a Import-Csv que no busque comas, que es lo que hace de forma predeterminada, sino otro valor.

Por ejemplo, si tiene un archivo con tabulaciones como separadores, puede leer el archivo de la siguiente manera:

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

Agregar Encabezados

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

De forma predeterminada, el cmdlet Import-Csv tratará la primera fila del archivo CSV como encabezados. Luego convertirá estos valores en propiedades de cada fila (objeto). Pero si tiene un archivo CSV que no tiene una fila de encabezado, puede usar el parámetro Header para definir uno usted mismo.

El parámetro Header evita que Import-CSV utilice su primera fila como encabezado y también le evita el problema de tener que abrir manualmente el archivo CSV para agregar encabezados usted mismo.

Para demostrar este comportamiento, abra el bloc de notas y copie/pegue el siguiente texto. Este texto representará un conjunto de datos con tres filas y dos columnas.

a,1
b,2
c,3

Guarde el archivo de texto como test.csv. No olvide habilitar las extensiones de tipo de archivo o encerrar el archivo entre comillas dobles para que no lo guarde accidentalmente con un nombre de archivo que termine en .csv.txt!

Ahora, use Import-CSV para leer el archivo CSV recién creado sin el parámetro Header e inspeccione la salida.

PS51> Import-Csv .\test.csv

a 1
---
b 2
c 3

Ten en cuenta que se utilizó la primera fila como las propiedades del objeto. A y 1 no son “etiquetas” que desees para las propiedades del objeto. A, b y c son letras mientras que 1, 2 y 3 son números. Necesitas definirlos con el parámetro Header de la siguiente manera:

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

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

Guardar archivos CSV con PowerShell

Si necesitas crear o guardar un archivo CSV a partir de objetos PowerShell, también puedes hacerlo de otra manera. Mientras que el cmdlet Import-Csv “convierte” un archivo CSV en objetos PowerShell, Export-Csv hace lo contrario. Este cmdlet “convierte” objetos PowerShell en un archivo CSV.

Al guardar un archivo CSV con Export-Csv, te permite luego ver o utilizar esos datos en otros sistemas.

Por ejemplo, puedo guardar todos los procesos en ejecución en mi computadora dirigiendo Get-Process al cmdlet Export-Csv.

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

El cmdlet Export-Csv es simple por naturaleza, pero hay un par de problemas a tener en cuenta.

Formato de salida antes de ejecutar Export-CSV

Como has visto anteriormente, Export-Csv, por sí mismo, realiza una conversión “cruda”. No agrega ningún formato especial enriquecido, no agrega colores, y así sucesivamente.

Uno de los problemas más comunes es intentar hacer que la salida se vea bonita antes de exportarla a un CSV. Muchos usuarios intentarán mejorar la apariencia de la salida antes de exportarla a un CSV. Pero estoy a punto de mostrarte que esto empeora las cosas.

Puedes abrir un archivo CSV en Microsoft Excel y aplicar cursiva, negrita, agregar colores y muchas otras cosas, pero si guardas el archivo como un CSV (en lugar de un libro de Excel), se perderá todo el formato. Un archivo CSV simplemente no es lo suficientemente “inteligente”.

Recuerda que los archivos CSV son simplemente archivos de texto plano con valores delimitados por comas (o a veces pestañas).Enviar el resultado de Import-Csv a un cmdlet de PowerShell Format-* no funcionará como se espera.

Según la documentación de Microsoft Export-Csv: “No formatees objetos antes de enviarlos al cmdlet Export-CSV. Si Export-CSV recibe objetos formateados, el archivo CSV contendrá las propiedades de formato en lugar de las propiedades del objeto.”

¿Por qué sucede esto?

Abre una ventana de PowerShell y crea algunos datos de ejemplo. Utilicemos el ejemplo Get-Process cubierto en la primera sección de este artículo. Pero esta vez, asigna la salida a una variable. Luego, pasa esos objetos de proceso al cmdlet Format-Table.

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

Al usar Format-Table, verás que ahora tienes una salida limpia y tabular.

Ahora guarda esta salida en otra variable.

PS51> $b = $a | Format-Table

Ahora visualiza las propiedades en ambas variables $a y $b con Get-Member. Este cmdlet te ayudará a entender por qué estos dos objetos aparentemente similares no se exportan a un archivo CSV de la misma manera:

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

La salida directamente de Get-Process devuelve: TypeName: System.Diagnostics.Process, mientras que la salida de Format-Table es completamente diferente. Devuelve muchos tipos diferentes con propiedades variables.

Si visualizas $a y $b en la consola, la salida parecería idéntica. Este comportamiento se debe al sistema de formato de PowerShell.

¿Cómo afecta esto a la salida de Export-Csv?

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

Export-Csv lee cada objeto tal como es. Cuando envías la salida a un cmdlet Format-*, estás cambiando la entrada que recibe Export-Csv. Esto luego afecta la salida que se guarda en tu nuevo archivo CSV.

Si vas a enviar la salida al cmdlet Export-Csv, no envíes la salida a ningún cmdlet Format-*.

Recuerda que los CSV están enfocados en los datos, no en el formato.

Añadiendo a un archivo CSV existente

A veces puede que tengas un archivo existente al que quieras agregar en lugar de crear uno completamente nuevo. Por defecto, Export-Csv sobrescribirá cualquier archivo especificado mediante el parámetro Path.

Si necesitas añadir datos a un CSV, utiliza el parámetro Append.

Digamos que tienes un bucle en el que deseas guardar cada objeto procesado en un archivo CSV. Para cada iteración, tienes un objeto diferente que te gustaría guardar en un archivo CSV. Como estás llamando a Export-Csv repetidamente, sobrescribirá ese archivo CSV si no utilizas el parámetro Append. Sin el parámetro Append, solo obtendrás el último objeto, lo cual en la mayoría de los casos no es el resultado deseado.

El siguiente ejemplo encuentra los primeros cinco procesos en ejecución. Luego, entra en un bucle foreach de PowerShell Import-Csv y graba las propiedades Name y ProductVersion en el archivo test.csv uno por uno.

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

Sin utilizar el parámetro Append, verás que solo el quinto proceso se mostrará en el archivo CSV.

Agregando Diferencias a un Archivo CSV

Es posible agregar solo las diferencias de propiedades a un archivo CSV existente con Export-Csv. Esto significa que si las columnas de una fila CSV y el objeto a grabar son diferentes, entonces adelante y agrégalos.

Para agregar solo las diferencias al archivo CSV, deberás utilizar los parámetros Append y Force juntos. Según la documentación de Microsoft “Cuando se combinan los parámetros Force y Append, se pueden escribir en un archivo CSV objetos que contienen propiedades no coincidentes. Solo se escriben en el archivo las propiedades que coinciden. Las propiedades no coincidentes se descartan”.

Para demostrar, crea un objeto con dos propiedades; Name y Age.

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

Ahora crea otro objeto con una propiedad Name y Zip.

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

Cada objeto tiene propiedades diferentes.

A continuación, crea un archivo CSV a partir del primer objeto y luego intenta agregar el segundo objeto al CSV sin el parámetro Force. Obtendrás un error.

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

Sin embargo, si usas el parámetro Force, Export-Csv funcionará correctamente.

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

Sin embargo, notarás que la columna Zip ha desaparecido en el archivo CSV. Usa Force con precaución. Puede que no proporcione el resultado deseado.

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

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

Export-CSV y la cadena #TYPE

De forma predeterminada, al usar Export-CSV sin parámetros adicionales, se incluirá una cadena #TYPE en la parte superior de tu archivo CSV. Esta cadena va seguida del tipo de objeto que Export-Csv recibió.

#TYPE System.Diagnostics.Process

En su mayoría, esta cadena no es realmente útil al consumir la salida. Esta cadena solo está ahí en caso de que necesites mantener el tipo de objeto del que provinieron las propiedades y valores.

Para eliminar esta cadena, utiliza el parámetro NoTypeInformation. Este parámetro elimina completamente esta cadena del CSV.

Ten en cuenta que a partir de PowerShell Core, esto ya no es necesario.

Resumen

Usar los cmdlets de PowerShell Import-CSV y Export-CSV te permite trabajar fácilmente con archivos CSV. Estos son dos cmdlets útiles que deberías usar con frecuencia al tratar con objetos y archivos CSV.

Mi esperanza es que con las explicaciones y ejemplos que he mostrado aquí, puedas tener una comprensión clara de las situaciones en las que puedes aprovechar estos cmdlets en tu beneficio.

¿Quieres más consejos como este? Echa un vistazo a mi blog personal de PowerShell.

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