Why does piping raw bytes work directly but fail through a function?

November 6, 2026 4 answers
Asked by brisketloom

This works when I pipe ImageMagick output straight to chafa, but not when I wrap chafa in a PowerShell function. What changes at the function boundary, and is there a reliable way to keep the data as raw bytes?

Answers

YIP!

The direct pipe between two native executables can pass standard output to standard input as bytes. Once a PowerShell function sits in the middle, the pipeline is PowerShellโ€™s object pipeline, not a transparent native-process byte pipe. The function does not automatically forward its incoming pipeline data to chafaโ€™s stdin.

So this is not just a matter of adding a parameter to the function. Even if it accepts pipeline input, that does not guarantee the original raw byte stream reaches the native program unchanged. For this use, keep the native commands adjacent, or use another mechanism that explicitly preserves the bytes.

Reply to this answer
luma+orbit

There are two separate issues here. The function needs to be written to accept pipeline input, and PowerShellโ€™s function pipeline is not the same thing as native stdin. A parameter block can solve the first part, but it does not turn the function into a raw-byte conduit.

If you only want a reusable wrapper, have it invoke chafa with its arguments, as you already do, but call it without expecting bytes piped into the function to flow through untouched. If the input must remain binary, keep the pipe directly between the executables.

m0onreceipt:

So adding a parameter marked for pipeline input would not be enough to preserve these bytes?

Reply to this answer
oddly_rainy

For this exact case, the simplest fix is to skip the function in the middle:

magick _.png -negate png:- | chafa.exe --size=70x -f sixel -

The trailing dash tells chafa to read from standard input. In the direct version, the shell connects the two native processes. Calling a PowerShell function instead changes the route, so it is no longer equivalent.

Reply to this answer
KETTLE-PIX

If the wrapper is mainly for convenience, consider making it construct or run the whole native command rather than trying to accept binary pipeline input. PowerShell functions are useful for passing and transforming PowerShell objects, but they are not a drop-in replacement for a native pipe when the payload is arbitrary bytes.

Also, @args only deals with the arguments passed to the function. It does not capture the previous commandโ€™s stdout and forward that as stdin.

Reply to this answer

Add your answer

Answers are reviewed before publication.

Related Discussions