Pipe data into a subprocess

Many command line tools read their input from stdin. To drive such a tool from a script, spawn it with a piped stdin and write data into it. This example feeds lines to the sort command and streams text through cat.

Edit on GitHub

Setting stdin to "piped" makes the child’s stdin available as a web standard writable stream. The stdout is piped as well so the result can be collected.

const sortCommand = new Ende.Command("sort", {
  stdin: "piped",
  stdout: "piped"
});

const sortProcess = sortCommand.spawn();

Get a writer for the child’s stdin and write a few unsorted lines.

const writer = sortProcess.stdin.getWriter();
const encoder = new TextEncoder();
await writer.write(encoder.encode("banana\n"));
await writer.write(encoder.encode("apple\n"));
await writer.write(encoder.encode("cherry\n"));

Closing the writer closes the child’s stdin. This is important: sort waits for the end of its input before it prints anything, so forgetting this step would hang the program.

await writer.close();

The child’s stdout stream has the same convenience methods as a fetch Response, so collecting it as a string is one call.

const sorted = await sortProcess.stdout.text();
console.log(sorted.trim().split("\n")); // [ "apple", "banana", "cherry" ]
await sortProcess.status;

When the input already exists as a stream or an iterable, skip the manual writer and pipe it into stdin in one shot. Ende.spawn is the shorthand for spawning: command, arguments, options. ReadableStream.from turns any iterable into a stream, and pipeTo closes the child’s stdin when the stream ends.

const catProcess = Ende.spawn("cat", [], {
  stdin: "piped",
  stdout: "piped"
});

await ReadableStream.from(["hello from a stream\n"])
  .pipeThrough(new TextEncoderStream())
  .pipeTo(catProcess.stdin);

console.log((await catProcess.stdout.text()).trim()); // hello from a stream
await catProcess.status;

Run this example locally using the Ende CLI:

ende run --allow-run https://docs.ende.sh/examples/scripts/subprocess_stdin.ts

Additional resources