4 ms·
I strongly disagree. A CLI is fundamentally for the benefit of humans interacting with the application, and not for the benefit of interprocess communication. W
by niftich 10y ago
I strongly disagree. A CLI is fundamentally for the benefit of humans interacting with the application, and not for the benefit of interprocess communication. When run interactively, a CLI should print human-useful information on the console.
Conversely, a structured way of exposing program outputs and state should be the preferred way of interprocess communication.
Because of convention and deliberate design choices, on the Unix command line, these two often find themselves in conflict. In my opinion, the solution isn't to compromise human usability to support machine-consumability of outputs.
- new_hackers 10y agoDisagree. A CLI is fundamentally for executing from the command line. Thus, embracing the power of the command shell is best practice. If you want a human to see it, put it on stderr. If you want a machine to see it, put it on stdout. Also I strongly agree with making it "structured" output. At minimum, a line-oriented record output is fairly easy to process downstream. EDIT: If it is an interactive console application (REPL), then stdout is okay i guess.
- smhenderson 10y agoWould a good compromise be to provide -q|--quiet to suppress extra, human readable messages when piping out to a different app?
- new_hackers 10y agoyes, that would be a good compromise
- dllthomas 10y agoAnother option is looking at isatty. I'm not sure how I feel about either.
- prodigal_erik 10y agoPlease provide a flag that bypasses the isatty check. I use nohup for anything slow or hard to rerun and then tail and/or grep the nohup.out file.
- dllthomas 10y agoYeah, I think that's definitely good advice. isatty can be a good way of deciding which defaults to use, but it shouldn't be the only way of accessing functionality. Note that the flag might say "pretend isatty said yes/no", or there might be a few flags that independently mediate all of the things set based on isatty.
- andrewstuart2 10y agoPersonally, I'd just say use a tab-delimited table by default. And put columns that may contain whitespace last. This way it's human readable and more easily awk/cut parseable. Unfortunately, with e.g. `docker ps`, I can't do as much as I'd like, because it's purely human readable by default. For example: ~ docker ps | awk '{print $7}' PORTS Up ago Up
- deleted 10y ago[deleted]
- skj 10y agoTo suppress the human messages while piping stdin, I add `2> /dev/null`.
- dllthomas 10y agoThere are plenty of times that that's appropriate, but note that it also hides genuine error messages on failure. It's not a good solution for making output less chatty - that's precisely what a `-q` option is for.
- restalis 10y agoIt may be even better to be quiet by default and explicitly turn on the verbose mode when the "extra, human readable messages" are actually needed.
- andrewstuart2 10y agoFor one, STDOUT and STDERR both go to the console, so it's very feasible to do both. Additionally, there are quite a few machine-readable layouts that are very very human readable (table or tsv, for example, as a huge swath of existing CLI programs output by default). I can very easily understand the output of `ps` or `ls` and I can very easily capture their output with a subshell: `for file in $(ls)` or `for process in $(ps -opid | tail -n +2);`, etc. The more ways there are to accomplish the same goal, the greater the number of users who can figure out some way of automating what they want to do. So yeah, make output format an option, with `--ouptut` or `--format` for those who want to use `jq` or some other tool, but strongly prefer defaulting to table output so that standard tools (awk, cut, etc.) can be integrated easily.