I'm trying to pipe a string into a program's STDIN without any trailing linefeeds (unless that string itself actually ends in a linefeed). I tried googling around, but I only found people trying to print to the console without a trailing linefeed, in which case Write-Host
takes a parameter -NoNewLine
. However, to pipe it on to another program, I need Write-Output
or similar which doesn't have such a parameter. Now it seems like Write-Output
isn't even the problem:
Z:\> (Write-Output "abc").Length
3
But as soon as I pipe it to another program and read the string there, I get an additional linefeed. For instance, I tried this Ruby snippet:
Z:\> Write-Output "abc" | ruby -e "p ARGF.read"
"abc\n"
I checked that the actual string received is abc\n
. The same happens in several other languages (at least C#, Java and Python), so I believe it's an issue with PowerShell, not the language doing the reading.
As a further test, I replaced Write-Output
itself with another Ruby script:
Z:\> ruby -e "$> << 'abc'"
abcZ:\>
(That is, there is definitely no \n
on the script's STDOUT.)
But again, when I pipe it into another script:
Z:\> ruby -e "$> << 'abc'" | ruby -e "p ARGF.read"
"abc\n"
I'm fairly convinced that it's the pipe which adds the linefeed. How do I avoid that? I actually want to be able to control whether the input ends in a linefeed or not (by including it in the input or omitting it).
(For reference, I also tested strings which already contain a trailing linefeed, and in that case the pipe doesn't add another one, so I guess it just ensures a trailing linefeed.)
I originally encountered this in PowerShell v3, but I'm now using v5 and still have the same issue.
Bruteforce approach: feed binary data to process' stdin. I've tested this code on the
cat.exe
from UnixUtils and it seems to do what you want:I will admit to having zero experience with the ruby -e "puts ARGF.read" command you are using after the pipe, but I think I can prove that the pipe doesn't adding a newline.
This gives me an output of:
I think you might want to start looking at the ruby -e "put AGRF.read" command and see if it is adding a newline after each read.
Do it a simple way create a cmd process and execute it
Worked perfect for piping information into stdin that I wanted,
Introduction
Here is my
Invoke-RawPipeline
function (get latest version from this Gist).Use it to pipe binary data between processes' Standard Output and Standard Input streams. It can read input stream from file/pipeline and save resulting output stream to file.
It requires PsAsync module to be able to launch and pipe data in multiple processes.
In case of issues use
-Verbose
switch to see debug output.Examples
Redirecting to file
findstr.exe /C:"Warning" /I C:\Windows\WindowsUpdate.log > C:\WU_Warnings.txt
Invoke-RawPipeline -Command @{Path = 'findstr.exe' ; Arguments = '/C:"Warning" /I C:\Windows\WindowsUpdate.log'} -OutFile 'C:\WU_Warnings.txt'
Redirecting from file
svnadmin load < C:\RepoDumps\MyRepo.dump
Invoke-RawPipeline -InFile 'C:\RepoDumps\MyRepo.dump' -Command @{Path = 'svnadmin.exe' ; Arguments = 'load'}
Piping strings
echo TestString | find /I "test" > C:\SearchResult.log
'TestString' | Invoke-RawPipeline -Command @{Path = 'find.exe' ; Arguments = '/I "test"'} -OutFile 'C:\SearchResult.log'
Piping between multiple processes
ipconfig | findstr /C:"IPv4 Address" /I
Invoke-RawPipeline -Command @{Path = 'ipconfig'}, @{Path = 'findstr' ; Arguments = '/C:"IPv4 Address" /I'} -RawData
Code: