- Out-File writes formatted output and must go at the end of the pipeline; it controls encoding and width.
- Redirection (>, >>) is equivalent in the basics, but in PowerShell 7.4 changed with natives.
- Real cases: from CSV with net user, counting of PDF, logs and changes to the Registry.
When working with PowerShell, sooner or later you need to save the output of your commands to a file. Exporting results to a text file is a simple way to audit, share, or process information later without relying on the console.
This guide provides a comprehensive and practical overview of how to output scripts and commands to text, using both Out-File and redirection operators. It includes real-world examples, encoding tips , line width considerations , and typical scenarios such as reading from CSV files, managing native command output, and logging . All explanations are presented in clear and straightforward Spanish (Spain).
What “exporting” means in PowerShell and how the Out-* family fits in
PowerShell provides a series of cmdlets whose verb is `Out` , designed to send output to destinations outside the PowerShell engine itself. When writing to a file, printer, or host, these cmdlets transform the objects into text, applying the console's formatting system.
This has a key consequence: the Out-* cmdlets must be at the end of the pipeline . If you place, for example, Out-Host in the middle of the pipeline, you'll interrupt the flow, and anything that comes after won't receive anything. The proof: Get-Process | Out-Host -Paging | Format-List won't display a list, but rather the default tabular view, because the output was already sent to the host before formatting.
The correct way is to reverse the order: Get-Process | Format-List | Out-Host -Paging . First, you choose the format, then you send the output to the corresponding destination. The same applies to Out-File , Out-Printer , or Out-Null (the latter discards everything it receives, useful for silencing results you don't need).
Out-File from top to bottom: syntax and behavior
The Out-File cmdlet writes the output to a file, applying the console's formatting. You can use it in two main ways: by normal path (ByPath) or by literal path (ByLiteralPath) when there are special characters that you don't want PowerShell to interpret.
Out-File <string> <Encoding>]
Out-File <Encoding>] -LiteralPath <string>
If you prefer classic redirection, > and >> are functionally equivalent to piping to Out-File without extra parameters (with some nuances), and since PowerShell 7.4 , the behavior of redirecting the standard output of native commands has changed. It's advisable to check about_Redirection if you redirect external executables to avoid surprises.
Keep in mind that `Out-File` does not return objects to the pipeline ; its purpose is to save text. The representation it writes is the same as what you would see in the console, so it may not be ideal for further processing unless you first convert it to strings or choose a controlled format with `Format-Table` or `Format-List`.
Out-File parameters explained in detail
To get the most out of exporting, it's essential to understand its parameters. These are the most important ones and how they help you in your day-to-day work.
- -FilePath Indicates the path to the output file. It is required in the ByPath set and has aliases like Path. If the file doesn't exist, it is created; if it exists, it is overwritten unless you specify otherwise.
- When you need to reference routes as they are written, -LiteralPath is your friend. It doesn't accept wildcards and exactly matches the specified string. Use it with single quotes if there are backslashes or escape characters.
- With -Append You add content to the end of an existing file without losing the previous content. Perfect for logs or incremental reports.
- If you don't want a file to be accidentally overwritten, -NoClobber blocks that operation and returns a message clarifying that the file already exists, avoiding scares.
- To force writing even when the file is read-only, -Strength invalidates that attribute. Note that this does not bypass security restrictions, only the read-only flag.
- With -Width You define the maximum width per line. Table-formatted output is usually adjusted to the host width; if you don't care about truncation, set a high width (e.g., 2000) or control the value globally with $PSDefaultParameterValues = 2000.
- Don't want a line break at the end? -NoNewline concatenates the resulting strings without adding new lines, useful when you are really interested join texts on the fly
- With -InputObject You can directly supply the objects or strings to be written without the need for piping. Ideal for pre-composed variables or results.
- To control what happens before executing, -WhatIf It shows you the action without performing it (dry test) and -Confirm It asks you for prior confirmation, which contributes security, when automating.
- Coding is crucial. -Encoding determines how the text is saved. The default is utf8NoBOM. Supports values such as ascii, unicode (UTF-16 LE), utf8, utf8BOM, utf8NoBOM, utf32, bigendianunicode, bigendianutf32, and oem (intended for MS-DOS or older consoles). Since PowerShell 7.4, you can use ansi for your culture's ANSI code page without manually entering the identifier. And starting with 6.2, you can pass numeric code page identifiers (e.g., 1251) or names like "windows-1251."
- In addition, Out-File supports the CommonParameters such as -Verbose, -ErrorAction, -Debug, etc., with which you can adjust the diagnostic and error behavior homogeneously.
Practical examples that you should master
Let's look at real-life scenarios that cover the most common situations, all of them rewritten so that you can copy and adapt them to your environment.
Create a file with the process list and read it . If the file doesn't exist, create it. This is ideal for capturing a snapshot of the system state.
Get-Process | Out-File -FilePath .\Process.txt
Get-Content -Path .\Process.txt
Prevent overwriting with -NoClobber. When the file already exists, it blocks the operation and displays an informational error instead of silently replacing it.
Get-Process | Out-File -FilePath .\Process.txt -NoClobber
Choose encoding and width . Saves in ASCII and limits each line to 50 characters (truncated, not resized). Useful for integrations with tools that expect a classic format.
$procs = Get-Process
Out-File -FilePath .\Process.txt -InputObject $procs -Encoding ascii -Width 50
Write from a non-FileSystem provider . You can list aliases from the Alias drive and copy them to a file in C:\TestDir without changing context.
Set-Location -Path Alias:
Get-ChildItem | Out-File -FilePath C:\TestDir\AliasNames.txt
Get-Content -Path C:\TestDir\AliasNames.txt
Set the default width across the entire scope . If you generate reports regularly, setting a high width prevents truncation regardless of the console window size.
$PSDefaultParameterValues = 2000
$logFile = "$PWD\logfile.txt"
Get-ChildItem Env:\ | Out-File $logFile
Get-Service -ErrorAction Ignore | Format-Table -AutoSize | Out-File $logFile -Append
Get-Process | Format-Table Id,SI,Name,Path,MainWindowTitle >> $logFile
$PSDefaultParameterValues.Remove('Out-File:Width')
Redirection in CMD and PowerShell: Important Differences
If you're working in the classic command prompt , you can send the output to TXT using the redirection operator. The general format is:
Comando > C:\Ruta\archivo.txt
For example, to save the output of nslookup you would do something like nslookup > C:\CMD\CMD.txt and open that file to review the result. It's a universal pattern in CMD.
In PowerShell, the recommendation is usually to pipe files to Out-File to have fine control over encoding and width. A basic way to do this is:
Get-Service | Out-File -FilePath C:\CMD\PowerShell.txt
You can then inspect it with Get-Content -Path C:\CMD\PowerShell.txt . If you notice that the output is truncated (very common with wide tables), increase the width with -Width or use the $PSDefaultParameterValues trick.
When the output must fit on a single wide line, one technique is to set the maximum integer supported by Width (2147483647), although for practical purposes 2000 is usually sufficient.
Read from CSV and export native command output (net user /domain)
A common use case is importing a CSV file with users or extracting data using PowerShell , and then, for each user, running `net user … /domain` and writing the output to a TXT file. If you do this within a `ForEach` loop and write to each iteration with `-Append`, it should work, but sometimes errors occur or only the output of the last item is retained.
A more robust way is to accumulate all the output and write it only once, reducing file openings/closings and avoiding race conditions with native processes:
Import-Csv 'C:\Desktop\domain.csv' |
ForEach-Object { net user $_.Username /domain } |
Out-File -FilePath 'C:\_test\user.txt' -Append
If you prefer to separate blocks by user to make the file more readable, you can inject manual delimiters. Write-Output helps add headers or blank lines:
Import-Csv 'C:\Desktop\domain.csv' |
ForEach-Object {
Write-Output ("----- USUARIO: {0} -----" -f $_.Username)
net user $_.Username /domain
Write-Output ""
} | Out-File -FilePath 'C:\_test\user.txt'
If you're still experiencing unusual behavior, there are alternatives: `Start-Process` with `-RedirectStandardOutput` for each user, or traditional redirection from cmd.exe. The important thing is that the file isn't locked and that all the text ends up in the same file without truncation or stream merging.
Write to the folder from which the script is run
Another common question is whether to always save in the script 's own folder or in the current folder. Use $PSScriptRoot for the script's path (when running from a .ps1 file) or $PWD for the current working directory in the session.
$destino = Join-Path $PSScriptRoot 'salida.txt'
Get-Process | Out-File -FilePath $destino
If you're running commands by pasting them into the console and you want the current path, `$PWD` or the alias ` .` will work. For clarity, compose the path using `Join-Path` to avoid slash issues.
Count PDF pages and record results in text
Imagine you're examining a directory and want to total the pages of all the PDFs using an external tool like pdfinfo . The idea is to iterate through the files, extract the "Pages" data, accumulate it, and generate a clear report.
$carpeta = 'C:\PRUEBA'
$totalPaginas = 0
$contadorArchivos = 0
Get-ChildItem -Path $carpeta -Filter *.pdf | ForEach-Object {
$info = & .\pdfinfo $_.FullName | Select-String -Pattern '(?<=Pages:\s*)\d+'
$paginas = $info.Matches.Value
$totalPaginas += $paginas
$contadorArchivos++
@{
Pdf = $_.Name
Paginas = $paginas
}
} | Out-File -FilePath (Join-Path $PWD 'detalle_pdfs.txt')
("Total de páginas: {0} en {1} archivos" -f $totalPaginas, $contadorArchivos) |
Out-File -FilePath (Join-Path $PWD 'detalle_pdfs.txt') -Append
This gives you a line-by-line listing of each PDF and a footer with the total. If you prefer a processable format, you could use CSV, but if your goal is a readable TXT file, Out-File is more than adequate.
Real-life case: logging in, filters with Select-String, and editing the Registry
Another very instructive scenario is a script that: identifies the current user, cross-references it with external lists, cleans files, extracts values, modifies a Registry key, and records everything that happens in a log. Although it may seem lengthy, it consists of simple, interconnected steps.
The typical workflow would be: capture the user with `whoami`, normalize it (for example, by removing the domain), search for it in an Active Directory list with `Select-String` , and write the match to a TXT file with `Set-Content`. Then, clean up empty lines with `Where-Object {$_.Trim() -ne »}` , and perform replacements with `-replace` to keep only the useful pattern.
Next, the first value is loaded using `Select-Object -First 1` (this avoids ambiguity if there are multiple matches). A second search is performed in another reference file, cleaned in the same way, and again the first result is selected. With this data, you can then query or export the relevant Registry branch.
A commonly used pattern is to extract the old key by exporting the branch with reg export , locating the line containing "User ID" with Select-String -Pattern "User ID" , cleaning quotes and the prefix with -replace , and keeping the value you are interested in as the "original value".
To apply the actual change, use Set-ItemProperty with the full path to HKEY_USERS based on the profile's SID, the value name "User ID," and the new data you determined earlier. And, very importantly, everything that happens is logged with Write-Output … | Out-File -Append (including time, user, SID, old and new values, etc.).
$hora = Get-Date
"Hora: $hora ; Usuario: $usuario ; ClaveOriginal: $valorOld ; NuevaClave: $valor ; SID: $sid" |
Out-File -FilePath "\\SERVIDOR\RUTA\usuarios.log" -Append
To close cleanly, remove temporary files with Remove-Item . A security tip: Out-File -Append maintains a consistently readable history, which is invaluable for subsequent audits if something goes wrong.
Out-Host, Out-Null, and Out-Printer: When They Matter and When They Don't
As we've already hinted, Out-Host essentially sends commands to the host (the console window). Its key feature is paging with -Paging on long lists, always placed at the end of the pipeline to avoid breaking the chain.
Out-Null is the sink. Everything that goes into it is immediately discarded. It's useful for commands with side effects when the output doesn't add value. Keep in mind that it doesn't eliminate errors : if the command doesn't exist or fails, you'll still see the message.
If you need to print , Windows has Out-Printer. You can send the output to the default printer or specify its display name (like a printer driver to a file), and PowerShell takes care of the rest.
Fine-tuning: format, ANSI and width without surprises
Because Out-File formats using the same system as the console, the output can sometimes be truncated. Controlling the width with -Width or the global default value avoids these problems when saving wide tables.
Starting with PowerShell 7.2, you can control how ANSI escape sequences are handled using `$PSStyle.OutputRendering` . If your output includes color or other decorations and you want to preserve or disable that behavior when exporting, adjust that preference before writing to the file.
In versions like Windows PowerShell 5.1 , the default Out-File format was Unicode. Today, with modern PowerShell, the default is utf8NoBOM , which is usually the most compatible. If an older tool insists on ASCII, specify it with `-Encoding ascii`. And if you're working with locale tools, ANSI (since version 7.4) is a convenient shortcut.
Quick tips for good practices
Whenever possible, choose Out-File over redirection if you need to control encoding, width, or existing file behavior. Redirection is fast, but less explicit, and its behavior changed with native support in 7.4.
When writing repeatedly during a loop, prioritize accumulating and writing only once , or if you must write per iteration, use -Append and avoid mixing multiple destinations in parallel that may compete for the same file.
If your script needs to save to its own folder, use $PSScriptRoot . If it's an interactive session, use $PWD. Join-Path protects against separator errors and improves portability.
When the goal is to process the data later , consider using Export-Csv or ConvertTo-Json instead of formatted text. If human readability is the priority (reports, logs), Out-File is ideal.
For unusual paths with special characters, -LiteralPath saves you headaches. And remember that Out-File doesn't return output to the pipeline: if you need to both print and save, use Tee-Object to duplicate streams.
If you're generating tabular reports, consider formatting them yourself with Format-Table or Format-List before writing. Controlling the formatting beforehand produces more stable results and avoids relying on the console's width.
The ecosystem of common cmdlets (-Verbose, -ErrorAction, etc.) also applies here. Enable -Verbose during testing to see what happens and disable it in production if you don't want noise.
This guide provides a clear roadmap: Out-File and similar tools transform what were previously objects into files, printers, or even the console itself. With the right combination of encoding, pipeline width, and order , your reports and logs will be reliable, readable, and ready to share or archive.
Passionate writer about the world of bytes and technology in general. I love sharing my knowledge through writing, and that's what I'll do on this blog, show you all the most interesting things about gadgets, software, hardware, tech trends, and more. My goal is to help you navigate the digital world in a simple and entertaining way.
Table of Contents
- 1 What “exporting” means in PowerShell and how the Out-* family fits in
- 2 Out-File from top to bottom: syntax and behavior
- 3 Out-File parameters explained in detail
- 4 Practical examples that you should master
- 5 Redirection in CMD and PowerShell: Important Differences
- 6 Read from CSV and export native command output (net user /domain)
- 7 Write to the folder from which the script is run
- 8 Count PDF pages and record results in text
- 9 Real-life case: logging in, filters with Select-String, and editing the Registry
- 10 Out-Host, Out-Null, and Out-Printer: When They Matter and When They Don't
- 11 Fine-tuning: format, ANSI and width without surprises
- 12 Quick tips for good practices
