dsherret / dax

Cross-platform shell tools for Deno and Node.js inspired by zx.
MIT License
964 stars 33 forks source link

Make it easier to pipe to files #206

Closed matklad closed 5 months ago

matklad commented 6 months ago

I am having trouble figuring out how to pipe command's stderr to a file :)

Here's the code I arraivied at:

const child = $`my-command`.stderr('piped').spawn();
child.stderr().pipeTo((await Deno.open("log.vopr")).writable)
await child

This typechecks, but throws at runtime Error: Bad file descriptor (os error 9), and it requires reaching for raw Deno.open APIs. As far as I understand, it isn't actually possible to do that with $.path API (or I am utterly failing at finding this in the API surface).

Ideally, I'd love to write just

await $`my-command`.stderr($.path("log.vopr"));

Not sure whether there's a gap in the API surface or in my doc reading abilities :)

(note: I really want to pipe there, as the output is gigs in size)

dsherret commented 6 months ago

Yeah, it's not very good atm (my knowledge of streams/web streams in JS when I wrote this was not great). This works for me in the latest version:

import $ from "https://deno.land/x/dax@0.36.0/mod.ts";

const txtFile = $.path("test.txt");
using file = txtFile.createSync();
await $`deno eval 'console.error(1); setTimeout(() => console.error(2), 2000);'`
  .env("NO_COLOR", "1")
  .stderr(file);

(I should update the docs with an example showing this... it's not in the docs)

await $`my-command`.stderr($.path("log.vopr"));

Yeah, that would be good because it could also handle automatically closing the file when the command is done.

matklad commented 6 months ago

Ah, right, indeed its the case of me being lost in the API maze! I guess I can name a couple stumbling blocks:

Not sure if theer's anything actionable here. Maybe defining ShellPipeWriterKind as

| "inherit"
| "null"
| "piped"
| "inheritPiped"
| WriterSync
| FsFileWrapper

which is of course redundant, but also clearly signals to the user "hey, you could pass in a file here".

dsherret commented 5 months ago

In 0.38.0 it's now possible to do:

await $`my-command 2> log.vopr`;
// or specified via a PathRef (ex. `$.path("somePath.txt")`)
await $`my-command 2> ${pathRef}`;
// or
await $`my-command`.stderr($.path("log.vopr"));