1

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.

1 Answer 1

2

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 :)

Sign up to request clarification or add additional context in comments.

1 Comment

Now we have a leading newline ;-) Not quite what I was asking for (I want to control the written data by myself and especially, what goes in, should go out (unmodified)), but a reimplementation is a valid solution and it can easily be adapted. Thx!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.