CLI application interface design, output to file, stdOut, ZON?

I am writing a CLI application that produces a binary non-executable artifact. It does not conform to any specific format, and I think convention would be to create a .bin file.

I think I also want my CLI application to be able to send it to stdOut (so users can pipe it) and send it to ZON (when that is merged) (as a file or to standard out).

How would you expect the CLI application to be structured? Like this?

Output to .zon file

gatorcat read-eeprom --format zon -o foo.zon

Output to .bin file

gatorcat read-eeprom --format zon -o foo.zon

Output to stdOut as binary? Is it ok to output nulls to stdOut?

gatorcat read-eeprom  --format bin

It is OK to ouput binary data to stdout, including null characters.

You could maybe always output to stdout, in which case your three examples could be written as:

gatorcat read-eeprom --format zon > foo.zon
gatorcat read-eeprom --format bin > foo.bin # typo in your example?
gatorcat read-eeprom --format bin

If you want to keep the -o option, it is customary to use - as the file name when you want to output to stdout:

gatorcat read-eeprom --format zon -o foo.zon
gatorcat read-eeprom --format bin -o foo.bin # typo in your example?
gatorcat read-eeprom --format bin -o -

Cheers!

4 Likes

My personal preference for textual output is simply to default to stdout, and let users use shell redirection to write it to a file, I actually don’t even care if there is dedicated --output argument in such cases.

For binary data, its output is meaningless when displayed in a terminal, as well as possibly quite large, I would definitely opt to make outputting to stdout an explicit action in this case, and not do so automatically just because a user didn’t specify an output file. As @gonzo pointed out, the common convention here is to use -.

3 Likes

In think in cases like this it’s best to look at existing tools, preferably from similar domain, and try to adhere to the conventions they’re using.
Related, although it doesn’t directly answer your question, but might be worth reading:
http://www.catb.org/~esr/writings/taoup/html/ch10s05.html

1 Like

In case it is relevant: I had issues with writing binary data to stdout on windows. I cannot remember the details any more, but I think the windows console api expects some text encoding. At the time I wanted to write a signal processing pipeline. After switching to windows it took me a while to realize that this was the issue.

Edit: If anyone is interested, here is the link to the the mentioned signal processing tool: lufe/goerzig: Simple frequency analyses tool based on the Goertzel algorithm. - Codeberg.org

One way to mitigate this issue is to check whether the stdout file is a TTY (terminal) by calling std.fs.File.isTty on it. That way, the program can avoid dumping binary data directly to the user’s terminal (unless specifically requested to) while still working as-is using a pipe or output to a file. Several common programs do things like this, such as ls formatting output more compactly when printing to a terminal (compare ls and ls | cat) and gzip (at least the GNU version) which applies the same sort of safety check:

$ echo hi | gzip
gzip: compressed data not written to a terminal. Use -f to force compression.
For help, type: gzip -h
$ echo hi | gzip >hi.gzip
# works
6 Likes