-
-
Save ScriptAutomate/0c53db9328ab329101f6bd6fba436f6f to your computer and use it in GitHub Desktop.
PowerShell function that emulates Out-File for creating UTF-8-encoded files *without a BOM* (byte-order mark).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<# | |
Prerequisites: PowerShell version 3 or above. | |
License: MIT | |
Author: Michael Klement <[email protected]> | |
#> | |
function Out-FileUtf8NoBom { | |
<# | |
.SYNOPSIS | |
Outputs to a UTF-8-encoded file *without a BOM* (byte-order mark). | |
.DESCRIPTION | |
Mimics the most important aspects of Out-File: | |
* Input objects are sent to Out-String first. | |
* -Append allows you to append to an existing file, -NoClobber prevents | |
overwriting of an existing file. | |
* -Width allows you to specify the line width for the text representations | |
of input objects that aren't strings. | |
However, it is not a complete implementation of all Out-File parameters: | |
* Only a literal output path is supported, and only as a parameter. | |
* -Force is not supported. | |
* Conversely, an extra -UseLF switch is supported for using LF-only newlines. | |
Caveat: *All* pipeline input is buffered before writing output starts, | |
but the string representations are generated and written to the target | |
file one by one. | |
.NOTES | |
The raison d'être for this advanced function is that Windows PowerShell | |
lacks the ability to write UTF-8 files without a BOM: using -Encoding UTF8 | |
invariably prepends a BOM. | |
Copyright (c) 2017, 2020 Michael Klement <[email protected]> (http://same2u.net), | |
released under the [MIT license](https://spdx.org/licenses/MIT#licenseText). | |
#> | |
[CmdletBinding()] | |
param( | |
[Parameter(Mandatory, Position=0)] [string] $LiteralPath, | |
[switch] $Append, | |
[switch] $NoClobber, | |
[AllowNull()] [int] $Width, | |
[switch] $UseLF, | |
[Parameter(ValueFromPipeline)] $InputObject | |
) | |
#requires -version 3 | |
# Convert the input path to a full one, since .NET's working dir. usually | |
# differs from PowerShell's. | |
$dir = Split-Path -LiteralPath $LiteralPath | |
if ($dir) { $dir = Convert-Path -ErrorAction Stop -LiteralPath $dir } else { $dir = $pwd.ProviderPath} | |
$LiteralPath = [IO.Path]::Combine($dir, [IO.Path]::GetFileName($LiteralPath)) | |
# If -NoClobber was specified, throw an exception if the target file already | |
# exists. | |
if ($NoClobber -and (Test-Path $LiteralPath)) { | |
Throw [IO.IOException] "The file '$LiteralPath' already exists." | |
} | |
# Create a StreamWriter object. | |
# Note that we take advantage of the fact that the StreamWriter class by default: | |
# - uses UTF-8 encoding | |
# - without a BOM. | |
$sw = New-Object System.IO.StreamWriter $LiteralPath, $Append | |
$htOutStringArgs = @{} | |
if ($Width) { | |
$htOutStringArgs += @{ Width = $Width } | |
} | |
# Note: By not using begin / process / end blocks, we're effectively running | |
# in the end block, which means that all pipeline input has already | |
# been collected in automatic variable $Input. | |
# We must use this approach, because using | Out-String individually | |
# in each iteration of a process block would format each input object | |
# with an indvidual header. | |
try { | |
$Input | Out-String -Stream @htOutStringArgs | % { | |
if ($UseLf) { | |
$sw.Write($_ + "`n") | |
} | |
else { | |
$sw.WriteLine($_) | |
} | |
} | |
} finally { | |
$sw.Dispose() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Configure git for more powers
Other information that may be helpful in
git
repos that are used on Windows systems:# Run this on Windows systems with repos that use tools expecting LF, too git config core.autocrlf input
You can optionally run
git config --global core.autocrlf input
, too, though this will havegit
treat all of your repos this way locally on your system..gitattibutes
in root of repoRelated
More info: GitHub Docs: Configuring Git to handle line endings