Tee-Object
does not have a -NoNewline
switch like many other output-to-file-cmdlets (e. g. Out-File
, Set-Content
). Under the hood, Tee-Object
uses Out-File
to write to a file, which adds a trailing newline by default.
As I (currently) cannot pass through the -NoNewline
switch through Tee-Object
, is there another way I can enforce that the underlying Out-File
won't add a trailing newline? Looking at the implementation of Out-File
, there might be now way, but maybe someone is aware of some tricks/hacks to achieve it anyway?
Some constraints:
- I want to use
Tee-Object
(or an alternative solution) in a pipeline - I do not want to post-process the files generated by
Tee-Object
(or an alternative solution), like opening them again and removing the (last) newline.
Code for reproduction:
"Test" | Tee-Object file | Out-Null
On Windows, the generated file file
will contain 6 bytes like shown in the following hexdump:
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ASCII
00000000 54 65 73 74 0D 0A Test..
Which, unfortunately, contains the additional bytes 0D 0A
a. k. a. `r`n
or CR&LF in Windows.
CodePudding user response:
You could roll your own and write a prefixed newline:
function Tee-StackProtectorObject {
param(
[Parameter(Mandatory=$true, Position=1, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
[AllowNull()]
[AllowEmptyCollection()]
[psobject]
$InputObject,
[Parameter(ParameterSetName='Path', Mandatory=$true, Position=0, ValueFromPipelineByPropertyName=$true)]
[string[]]
$Path,
[Parameter(ParameterSetName='LiteralPath', Mandatory=$true, ValueFromPipelineByPropertyName=$true)]
[Alias('PSPath')]
[string[]]
$LiteralPath
)
begin {
# Determine newline character sequence at the start (might differ across platforms)
$newLine = [Environment]::NewLine
# Prepare parameter arguments for Add-Content
$addContentParams = @{ NoNewLine = $true }
if($PSCmdlet.ParameterSetName -eq 'Path'){
$addContentParams['Path'] = $Path
}
else {
$addContentParams['LiteralPath'] = $LiteralPath
}
}
process {
# Write to file twice - first a newline, then the content without trailling newline
Add-Content -Value $newLine @addContentParams
Add-Content -Value $InputObject @addContentParams
# Write back to pipeline
Write-Output -InputObject $InputObject
}
}
Note that, unlike Tee-Object
, the function above is in perpetual "append mode". Refactoring it to support both appending and overwriting is left as an exercise for the reader :)