PowerShell Set-Content and Out-File - what is the difference?

powershell

Solution

Here's a summary of what I've deduced, after a few months experience with PowerShell, and some scientific experimentation. I never found any of this in the documentation :(

[Update: Much of this now appears to be better documented.]

Read and write locking

While `Out-File` is running, another application can read the log file.

While `Set-Content` is running, other applications cannot read the log file. Thus never use `Set-Content` to log long running commands.

Encoding

`Out-File` saves in the `Unicode` (`UTF-16LE`) encoding by default (though this can be specified), whereas `Set-Content` defaults to `ASCII` (`US-ASCII`) in PowerShell 3+ (this may also be specified). In earlier PowerShell versions, `Set-Content` wrote content in the `Default` (ANSI) encoding.

Editor's note: PowerShell as of version 5.1 still defaults to the culture-specific `Default` ("ANSI") encoding, despite what the documentation claims. If ASCII were the default, non-ASCII characters such as `ü` would be converted to literal `?`, but that is not the case: `'ü' | Set-Content tmp.txt; (Get-Content tmp.txt) -eq '?'` yields `$False`.

PS > $null | out-file outed.txt
PS > $null | set-content set.txt
PS > md5sum *
f3b25701fe362ec84616a93a45ce9998 *outed.txt
d41d8cd98f00b204e9800998ecf8427e *set.txt

This means the defaults of two commands are incompatible, and mixing them will corrupt text, so always specify an encoding.

Formatting

As Bartek explained, `Out-File` saves the fancy formatting of the output, as seen in the terminal. So in a folder with two files, the command `dir | out-file out.txt` creates a file with 11 lines.

Whereas `Set-Content` saves a simpler representation. In that folder with two files, the command `dir | set-content sc.txt` creates a file with two lines. To emulate the output in the terminal:

PS > dir | ForEach-Object {$_.ToString()}
out.txt
sc.txt

I believe this formatting has a consequence for line breaks, but I can't describe it yet.

File creation

`Set-Content` doesn't reliably create an empty file when `Out-File` would:

In an empty folder, the command `dir | out-file out.txt` creates a file, while `dir | set-content sc.txt` does not.

Pipeline Variable

`Set-Content` takes the filename from the pipeline; allowing you to set a number of files' contents to some fixed value.

`Out-File` takes the data as from the pipeline; updating a single file's content.

Parameters

`Set-Content` includes the following additional parameters:

- Exclude

- Filter

- Include

- PassThru

- Stream

- UseTransaction

`Out-File` includes the following additional parameters:

- Append

- NoClobber

- Width

For more information about what those parameters are, please refer to help; e.g. `get-help out-file -parameter append`.

Problem

In PowerShell, what's the difference between `Out-File` and `Set-Content`? Or `Add-Content` and `Out-File -append`? I've found if I use both against the same file, the text is fully mojibaked. (A minor second question: `>` is an alias for `Out-File`, right?)

Original source