Working with Files
PowerShell has built-in mechanisms for working with various file types, the most common of which being test, csv and json.
TXT, or any text-based file
Text files can be read from and written to by using Get-Content for reading, and either Set-Content, Add-Content or Out-File for writing.
Reading text files
When reading a file, the default behaviour is to read a file as an array of strings, splitting the file by line breaks (LF vs CRLF has no effect).
To read a 10-line file into an array of 10 strings, you would run
$MyStrings = Get-Content -Path myfile.txtIf, however, you wanted to read the file as a single string, you would add the -Raw parameter to the command, like this:
$MyString = Get-Content -Path myfile.txt -RawThe
-Rawparameter is almost always used when reading json files. See below.
Writing Text Files
If you have a string (or strings) you wish to write to a file, you can use Set-Content to replace the entire contents of the file, or Add-Content to append to the end of the file. For example, to write a single string to a file, you would run
$MyString = "Hello, World!"
Set-Content -Path myfile.txt -Value $MyStringThis would produce a text file whose entire contents were "Hello, World!". If you wanted to append a string to the end of the file instead, you would run
$MyString = "Hello, again!"
Add-Content -Path myfile.txt -Value $MyStringThis would leave the original contents of the file intact, and add "Hello, again!" to the end of the file.
Whether or not your file ends with a new line character depends on the
-NoNewLineparameter, which bothSet-ContentandAdd-Contentsupport. By default, both commands will add a new line character to the end of the file after writing. But, if you useAdd-Contentthe new text you add will be appended immediately after the last character the file had previously. So, if you were to do this:
"Line 1" | Set-Content -Path myfile.txt -NoNewLine
"Line 2" | Add-Content -Path myfile.txtThe resulting file would contain "Line 1Line 2".
Alternatively, you can use Out-File, which contains an -Append parameter for appending data rather than overwriting. This function behaves almost exactly the same as Set-Content and Add-Content, but without some of the built-in formatting. It also does not hold open the file handle, so it is better for writing to files that are being read by other processes.
When using
Set-ContentorOut-File, if the file exists the command will error unless you add the-Forceparameter, which will overwrite the file. If you useAdd-Content, the command will not error, and will simply append to the end of the file.
Encoding and line endings
When writing data to a text-based file, you sometimes need to consider encoding and line endings, to ensure the file is compatible with other users. Previously, both Set-Content and Out-File defaulted to using ASCII text-encoding, which does not handle many special characters (such as those found in cyrilic or asian languages). It is highly recommended to use the -Encoding UTF8 parameter when writing to text files, as this will ensure that all characters are preserved. For example:
$MyString = "Hello, World!"
Set-Content -Path myfile.txt -Value $MyString -Encoding UTF8Similarly, line breaks tend to differ between Windows and Linux-based platforms. Windows uses to characters, the carriage return (CR) and the line feed (LF), whereas Linux platforms just use the line feed. PowerShell does not have a mechanism for specifying line endings when writing your files, but if you are writing data and want to ensure line endings are uniform you can use the -NoNewLine parameter to avoid adding a new line character, and instead add your own line breaks using the "n" (LF) or "rn" (CRLF) characters. For example, to write a file with Linux-style line endings, you would run:
$MyString = "Line 1`nLine 2"
Set-Content -Path myfile.txt -Value $MyString -NoNewLineJSON files
PowerShell is extremely powerful when working with JSON data, as it can convert that data into a native PowerShell object, allowing you to sort, filter and otherwise manipulate the data much more easily (and you don't have to muck about with complex jq queries).
Reading JSON Data
To get JSON text into a PowerShell object, you would first read it as a string, then pipe it to the ConvertFrom-Json command, like this:
$MyObject = Get-Content myfile.json -Raw | ConvertFrom-JsonThis will leave you with a PSCustomObject, $MyObject, which you can then manipulate as you would any other object. For example, if the JSON file contained an array of objects, you could filter them like this:
$FilteredObjects = $MyObject | Where-Object { $_.Property -eq "Value" }Writing JSON Data
Writing JSON data is very simple in PowerShell, and only really has one caveat. To write a PowerShell object to a JSON file, you would use the ConvertTo-Json command then pipe that to Set-Content or Out-File, like this:
$MyObject | ConvertTo-Json | Set-Content -Path myfile.json -Encoding UTF8The only concern here is that ConvertTo-Json has a default depth of 2, which means that if your object contains nested objects deeper than 2 levels, they will be truncated. To avoid this, you can use the -Depth parameter to specify how deep you want to go. For example, to convert an object with a depth of 5, you would run:
$MyObject | ConvertTo-Json -Depth 5 | Set-Content -Path myfile.json -Encoding UTF8The
-Depthparameter has a maximum value of 100, which you will only really ever exceed if your object has circular references, which will then throw an error. As such, since you may not know offhand the depth of your object, it is generally best practice to use the maximum value of 100, unless you know for sure that your object is shallower than that.
CSV Files
PowerShell natively supports reading from and writing to CSV files easily, which makes it very convenient to represent object data in a user-friendly format.
Reading CSV Data
You can convert CSV data into a PowerShell object by using the Import-Csv command, like this:
$MyObject = Import-Csv -Path myfile.csvThis will create an array of PSCustomObjects, with each entry having properties based on the column headers in the CSV file. You can then manipulate this object as you would any other PowerShell object, like this:
$FilteredObjects = $MyObject | Where-Object { $_.Property -eq "Value" }Writing CSV Data
If you have data as an array of objects, you can write it to a CSV file using the Export-Csv command, like this:
$MyObject | Export-Csv -Path myfile.csvIn Windows PowerShell (v5.1) there is an additional line added to the top of the CSV file, which is a comment line containing the text
#TYPE System.Management.Automation.PSCustomObject. This is not present in PowerShell 6+, and can be avoided in Windows PowerShell by using the-NoTypeInformationparameter. Or, better yet, upgrade to PowerShell 7 and avoid this issue entirely, as well as many, many others.
One thing to note is that if you havea an array of objects whose properties are not always the same, e.g. some members of the array have a certain property and others do not, you may end up with missing columns in your CSV file. This is because Export-Csv will only create columns for properties which exist on the first object in the array. If you want to ensure that all properties are included, you can use the -Force parameter, which will create a column for every property found in the entire array, like this:
$MyObject | Export-Csv -Path myfile.csv -ForceExcel Data
PowerShell has no support for working natively with Excel files, but you can use the ImportExcel module to achieve. You can install it by running:
Install-Module ImportExcelOnce this is installed you can export your data into multiple worksheets, use features like AutoSize, add tables etc. Check out the ImportExcel module (opens in a new tab) for more information on how to use it.