---
title: "Master Import-Csv and Other CSV Commands in PowerShell"
description: "Learn how to use the Import-Csv cmdlet with a foreach loop and other CSV commands in PowerShell."
canonical: "https://adamtheautomator.com/import-csv/"
---

# Master Import-Csv and Other CSV Commands in PowerShell

> Learn how to use the Import-Csv cmdlet with a foreach loop and other CSV commands in PowerShell.

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

---

ATA Learning

Tap to hide

[

ATA Learning

](/)

*   [Home](/)
*   [Tutorials](/tutorials/)
*   [Instructors](/author/)
*   [Advertising](/advertising/)
*   [Recommended Resources](/resources/)
*   [About Adam](/about-adam/)

Search for:  

*   [](https://twitter.com/adbertram)
*   [](https://github.com/Adam-the-Automator)
*   [](https://www.linkedin.com/company/adam-the-automator-llc)
*   [](/feed/)

![Master Import-Csv and Other CSV Commands in PowerShell](https://adamtheautomator.com/wp-content/uploads/2019/09/spreadsheet-3324169_1280.jpg)

# Master Import-Csv and Other CSV Commands in PowerShell

[![](https://secure.gravatar.com/avatar/06ab692f58fa7256ef14d0c099c863b6a12b9692e9c117a0337cc6468f359714?s=192&d=mm&r=g)Nathan Kasco](https://adamtheautomator.com/author/nate/)4 September 20197 min. read

Categories: [IT Ops](/category/it-ops/)

Tags:[PowerShell](/tag/powershell/)

Table of Contents

*   [Reading CSV Files with Import-Csv](#reading-csv-files-with-powershell)
*   [Non CSV Files](#non-comma-separated-files)
*   [Adding Headers](#adding-headers)
*   [Saving CSV Files with PowerShell](#saving-csv-files-with-powershell)
*   [Formatting Output Prior to Running Export-CSV](#formatting-output-prior-to-running-export-csv)
*   [Appending to a CSV File](#appending-to-a-csv-file)
*   [Appending Differences to a CSV FIle](#appending-differences-to-a-csv-file)
*   [Export-CSV and the #TYPE String](#export-csv-and-the-type-string)
*   [Summary](#summary)

The PowerShell `Export-Csv` cmdlet and the PowerShell `Import-Csv` cmdlets allow administrators to import CSVs via _foreach_ loop, use `Export-Csv` to append CSVs and export arrays to a CSV file and a whole lot more.

In this article you will learn about many common scenarios in which you can use PowerShell to manage CSVs like:

*   Reading CSV Files with PowerShell
*   Saving CSV Files with PowerShell
*   Formatting Output Prior to Running [`Export-CSV`](https://adamtheautomator.com/export-csv/ "Export-CSV")
*   Appending to a CSV
*   Appending Differences to an Existing File
*   `Export-CSV` and the `#TYPE` String

If you are unfamiliar with the inner workings of CSV files, they are text files that follow a standard format of literally comma separating your values in a table. You can [create a CSV file in PowerShell](https://adamtheautomator.com/teams-webhooks/) using the `Export-Csv` cmdlet and piping one or more objects to it.

The command below finds the first two running processes and passes the objects generated to the `Export-Csv` cmdlet. The `Export-Csv` cmdlet then creates a CSV file called _processes.csv_ in the root of your system drive (most likely _C:\\_).

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

Now open _processes.csv_ with notepad. You should see `"Name","SI","Handles","VM"` at the top as headers. You will also see `#TYPE System.Diagnostics.Process`, which may not make that much sense now. Don’t worry, we will cover that string in this article.

If this CSV work is turning into repeat spreadsheet analysis, compare [PopAi AI Sheets for spreadsheet editing, report generation, and document data extraction](https://sheets.popai.pro/?sharedid=&irpid=1454808&irgwc=1&afsrc=1) before choosing a paid AI spreadsheet tool.

## Reading CSV Files with Import-Csv

> _Want more tips like this? Check out my [personal PowerShell blog](https://nkasco.com/FriendsOfATA)._

PowerShell has a couple of commands that allow you to read text files. Those commands are [`Get-Content`](https://adamtheautomator.com/powershell-get-content/ "Get-Content") and `Import-Csv`. Each of these two cmdlets technically read the file the same way. But `Import-Csv` takes it one step further. `Import-Csv` understands the underlying structure of not just a text file but a CSV file.

Since a CSV file follows a certain schema, `Import-Csv` understands the CSV schema. This cmdlet only reads the text file from disk but also converts the rows in the CSV file to PowerShell objects.

### Non CSV Files

Typically, a CSV’s data is _comma_\-separated but there are times when a CSV (not technically a CSV at that point though) has data separated with a different delimiter. Those delimiters are sometimes a tab or perhaps a semicolon.

If you have CSV with a different delimiter, you can use the `Delimiter` parameter. This parameter tells `Import-Csv` to not look for commas, which is does by default, but for another value.

For example, if you have a tab-separated file, you can read the file like below:

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

### Adding Headers

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

By default, the `Import-Csv` cmdlet will treat the top row of the CSV file as headers. It will then convert these values in properties of each row (object). But if you have a CSV file that does not have a header row, you can use the `Header` parameter to define one yourself.

The `Header` parameter prevents `Import-CSV` from using your first row as your header and also saves you a headache from having to manually open up the CSV file to add headers yourself.

To demonstrate this behavior, open up notepad and copy/paste the text below. This text will represent a dataset with three rows and two columns.

```powershell
a,1
b,2
c,3
```

Save the text file as _test.csv_. Don’t forget to enable file type extensions or enclose the file with double quotes so that you don’t accidentally save it as a file ending in _.csv.txt_!

Now, use `Import-CSV` to read the recently-created CSV file without the `Header` parameter and inspect the output.

```powershell
PS51> Import-Csv .\test.csv

a 1
---
b 2
c 3
```

Notice that it used the first row as the object properties. `A` and `1` aren’t “labels” you want for the object properties. `A`, `b` and `c` are letters while `1`, `2` and `3` are numbers. You need to define those with the `Header` parameter like below:

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

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

## Saving CSV Files with PowerShell

If you need to create or save a CSV file from PowerShell objects, you can also go the other way. While the `Import-Csv` cmdlets “converts” a CSV file to PowerShell objects, `Export-Csv` does the opposite. This cmdlet “converts” PowerShell objects to a CSV file.

By saving a CSV file with `Export-Csv` allows you to later view or use that data in other systems.

For example, I can save all running processes on my computer by piping `Get-Process` to the `Export-Csv` cmdlet.

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

The `Export-Csv` cmdlet is simple in nature but there are a couple gotchas to look out for.

### Formatting Output Prior to Running Export-CSV

As you’ve seen above, `Export-Csv`, by itself does a “raw” conversion. It doesn’t add any special rich-text formatting, add any colors and so on.

One of the most common gotchas is attempting to make output look pretty prior to exporting to a CSV. Many users will attempt to make the output look better prior to exporting to a CSV. But I’m about to show you that make things worse.

You can open a CSV in Microsoft Excel and italicize, bold, add colors and many other things but if you save the file as a CSV (rather than an Excel workbook), all formatting will be erased. A CSV file simply isn’t “smart” enough.

Recall that CSV files are just plain text files with values delimited by commas (or sometimes tabs). __Piping `Import-Csv` to a_ `_Format-_*` PowerShell cmdlet will not work as expected._

Per [Microsoft Export-Csv documentation](https://docs.microsoft.com/en-us/powershell/module/Microsoft.PowerShell.Utility/Export-Csv?view=powershell-5.0): “Do not format objects before sending them to the `Export-CSV` cmdlet. If `Export-CSV` receives formatted objects the CSV file contains the format properties rather than the object properties.”

Why is this?

Open up a PowerShell window and create some dummy data. Let’s use the `Get-Process` example covered in the first section of this article. But this time, assign the output to a variable. Then, pipe those process objects to the [`Format-Table`](https://adamtheautomator.com/powershell-format-table/) cmdlet.

```powershell
PS51> $a = Get-Process
PS51> $a | Format-Table
```

![Using Format-Table](https://adamtheautomator.com/wp-content/uploads/2020/06/Then-pipe-those-process-objects-to-the-Format-Table-cmdlet..png "image_tooltip")

Using `Format-Table`

You can see using `Format-Table`, you now have a clean, tabular output.

Now save this output to another variable.

```powershell
PS51> $b = $a | Format-Table
```

Now view the properties on both the `$a` and `$b` variable values with `Get-Member`. This cmdlet will help you understand why these two seemingly like objects don’t export to a CSV file the same way:

```powershell
PS51> $a | Get-Member
```

![System.Diagnostics.Process object type](https://adamtheautomator.com/wp-content/uploads/2020/06/This-cmdlet-will-help-you-understand-why-these-two-seemingly-like-objects-dont-export-to-a-CSV-file-the-sa.png "image_tooltip")

System.Diagnostics.Process object type

```powershell
PS51> $b | Get-Member
```

![Format-Table's many object types](https://adamtheautomator.com/wp-content/uploads/2020/06/The-output-directly-from-Get-Process-returns-1-1024x880.png "image_tooltip")

`Format-Table`‘s many object types

The output directly from `Get-Process` returns: `TypeName: System.Diagnostics.Process`  whereas the output from `Format-Table` is completely different. It returns many different types with varying properties.

If you view `$a` and `$b` in the console, the output would look identical. This behavior is due to [PowerShell’s formatting system.](https://docs.microsoft.com/en-us/powershell/scripting/samples/using-format-commands-to-change-output-view?view=powershell-6)

How does this affect the output of `Export-Csv`?

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

`Export-Csv` reads each object as-is. When you pipe output to a `Format-*` cmdlet, you’re changing the input that `Export-CSV` receives. This then affects the output that gets saved into your new CSV file.

If you’re going to be piping output to the `Export-Csv` cmdlet, do not pipe output to any `Format-*` cmdlet.

Remember that CSVs are focused on data, not formatting.

## Appending to a CSV File

Sometimes you might have an existing file that you want to add to rather than creating a new one entirely. By default `Export-Csv` will overwrite any file specified via the `Path` parameter.

If you need to append data to a CSV, use the `Append` parameter.

Let’s say you have a loop that you want to save each object processed to a CSV. For every iteration, you have a different object you’d like to save to a CSV file. Since you’re calling `Export-Csv` repeatedly, it will overwrite that CSV file if you don’t use the `Append` parameter. Without the `Append` parameter, you will only get the _last_ object, which in most cases is not desired output.

The example below is finding the first five running processes. It’s then entering into a PowerShell `Import-Csv` [foreach](https://adamtheautomator.com/powershell-foreach/ "foreach") loop and recording the `Name` and `ProductVersion` properties to the _test.csv_ file one at a time.

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

Without using the `Append` parameter, you’ll see that only the fifth process will show in the CSV file.

## Appending _Differences_ to a CSV FIle

It’s possible to only append property difference to an existing CSV file with `Export-Csv`. This means that if a CSV row’s columns and the object to record are different, then go ahead and append them.

To only append differences to the CSV file, you’ll need to use the `Append` and `Force` parameters together. According to the Microsoft documentation “When `Force` and `Append` parameters are combined, objects that contain mismatched properties can be written to a CSV file. Only the properties that match are written to the file. The mismatched properties are discarded.”

To demonstrate, create one object with two properties; `Name` and `Age`.

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

Now create another object with a `Name` and `Zip` property.

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

Each object has differing properties.

Next, create a CSV file from the first object then attempt to append the second object to the CSV without the `Force` parameter. You’ll receive an error.

```powershell
PS51> $Content | Export-CSV -Path .\User.csv -NoTypeInformation
PS51> $OtherContent | Export-CSV -Path .\User.csv -NoTypeInformation -Append
```

![Export-Csv without Force](https://adamtheautomator.com/wp-content/uploads/2020/06/second-object-to-the-CSV-without-the-Force-parameter.-You’ll-receive-an-error-1024x88.png "image_tooltip")

`Export-Csv` without `Force`

However, if you use the `Force` parameter, `Export-Csv` will work great.

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

However, you’ll notice that the `Zip` column is gone in the CSV file. Use `Force` with care. It may not provide the intended output.

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

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

## `Export-CSV` and the `#TYPE` String

By default, using `Export-CSV` with no additional parameters will include a `#TYPE` string at the top of your CSV file. This string is then followed by the type of object `Export-Csv` received.

```powershell
#TYPE System.Diagnostics.Process
```

Most of the time, this string isn’t actually useful when consuming output. This string is only there in case you need to maintain the type of object that the properties and values came from.

To remove this string, use the `NoTypeInformation` parameter. This parameter removes this string from the CSV entirely.

Note that as of PowerShell Core, this is no longer necessary.

## Summary

Using the `Import-CSV` and `Export-CSV` PowerShell cmdlets allow you to easily work with CSV files. These are two useful cmdlets that you should use frequently when dealing with objects and CSV files.

My hope is that with the explanations and examples that I have displayed here that you will be able to have a clear understanding of situations where you can leverage these cmdlets to your benefit.

Want more tips like this? Check out my [personal PowerShell blog](https://nkasco.com/FriendsOfATA).

Share this article

[Share on X](https://twitter.com/intent/tweet?url=https%3A%2F%2Fadamtheautomator.com%2Fimport-csv%2F&text=Master%20Import-Csv%20and%20Other%20CSV%20Commands%20in%20PowerShell)[Share on Facebook](https://www.facebook.com/sharer/sharer.php?u=https%3A%2F%2Fadamtheautomator.com%2Fimport-csv%2F)[Share on LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fadamtheautomator.com%2Fimport-csv%2F)

## Related Posts

![](https://adamtheautomator.com/wp-content/uploads/2026/06/26995-troubleshoot-dns-issues-powershell-codex.webp)

### [Troubleshoot DNS Issues with PowerShell](/troubleshoot-dns-issues-powershell/)

Troubleshoot DNS issues with PowerShell by testing name resolution, DNS client settings, cache entries, and network connectivity in a repeatable workflow.

![](https://adamtheautomator.com/wp-content/uploads/2025/10/image_2025-10-24_095322075.png)

### [Migrating from PowerShell 6 to 7.5: Breaking Changes/New Features](/migrating-powershell-6-to-7-5/)

Migrate from PowerShell Core 6 to 7.5: breaking changes, features, and testing tips.

![](https://adamtheautomator.com/wp-content/uploads/2025/06/featured-image-6.png)

### [How to Add Timeouts to Pester Tests with PowerShell Runspaces](/pester-test-timeout-runspaces/)

Prevent Pester tests from hanging indefinitely using PowerShell runspaces. Learn to handle variable scoping, module loading, TestDrive access, and stream capture challenges with timeout protection.

## Categories

*   [IT Ops](/category/it-ops/)
*   [Cloud](/category/cloud/)
*   [DevOps](/category/devops/)
*   [Home Ops](/category/home-ops/)
*   [Information Security](/category/infosec/)
*   [Software Development](/category/software-development/)

## Site

*   [Home](/)
*   [Tutorials](/tutorials/)
*   [Instructors](/author/)
*   [Advertising](/advertising/)
*   [Recommended Resources](/resources/)
*   [About Adam](/about-adam/)

Copyright 2026© ATA Learning | [Privacy Policy](/privacy/)
