2

Writing a CLI tool, I'm facing a conundrum.

The tool is supposed to detect faces in images and blur them automatically. However, sometimes only one of those things should be done to allow marking additional faces manually with an external tool. So there are three behaviours I want to support:

  1. Detect faces and blur them in one go
  2. Only detect faces
  3. Only blur faces

My idea of solving this were two mutually exclusive options, something like --only-detect and --only-blur.

However, a coworker suggested that it might make more sense to have --detect and --blur, so that using both options would lead to the same behaviour as using none, but I find this to be less intuitive.

My question now is: Are there any conventions I can follow to make this decision? I found the POSIX Utility Conventions, and they do mention mutually exclusive groups, but nothing that is helpful here.

  • 2
    --only-foo is not something I think I've ever encountered in a tool; there's a few that do --no-foo, and --no-blur --no-detect wouldn't be mutually exclusive, nor would ` ` be the same as --blur --detect. – Ulrich Schwarz Nov 14 '17 at 17:37
  • Why not write two programs? – Charles Diploma Nov 14 '17 at 17:40
  • @UlrichSchwarz That is very useful information! In that case, what would no options do? Just nothing? Or print the help text? Or did you mean to say no options would not be the same as --no-blur --no-detect? – iFreilicht Nov 14 '17 at 17:51
  • 1
    @CharlesDiploma because most of the time, they are executed together. Executing them separately is a special use-case that's only useful in some specific cases. – iFreilicht Nov 14 '17 at 17:54
  • 1
    @iFreilicht if the most common action is to do both, then you should make that the default. After that, you could have --action=blur, --action=detect and --action=both and state that the default is --action=both. Or just abbreviate those to --blur, --detect and --both, so that no-one needs to complain about having to type too much... (of course, if you ever add any functions, the "both" option starts to seem odd.) But whatever you do, document the options and the default. Other than that, I think it's just up to you as the author. – ilkkachu Nov 14 '17 at 18:25
5

POSIX just says (regarding mutually exclusive command line options in POSIX utilities):

The use of conflicting mutually-exclusive arguments produces undefined results, unless a utility description specifies otherwise.


Some command line tools have conflicting command line options (such as both a --silent option and a --verbose option). In the case that both options are used when invoking the tool, if allowed, the last parsed option (the one last on the line) usually wins.

The last one of --blur and --detect would be used. The documentation would specify what options were exclusive.

Compare ls -l -1 with ls -1 -l, for example.


Other tools simply disallow conflicting command line options, giving the user a diagnostic message on the standard error stream and exiting with a non-zero exit code when such a situation occurs.

Your code would error out if both --blur and --detect were used.

This is done in e.g. cut which has conflicting flags -b, -c and -f.


Some tools may provide a different effect depending on what name it is invoked as. So, you could have two names (hard links) for your tool, one called detectface and another called blurface. These would be the exact same binary but the program would determine what name it was invoked as to figure out what operation to perform.

This is common on system where some shell masquerades as both /bin/sh (a POSIX shell) and as itself (e.g. bash on Linux, or ksh on OpenBSD) and that switches to "POSIX sh mode" when invoked as sh, or you might have a compiler that compiles both C and C++ code and switches mode depending on whether it's invoked as cc or c++, etc. (both gcc and clang does this).

  • Very interesting info about the symlink-dependant behaviour. I think your answer really shows that mutually exclusive options are to be avoided when possible. – iFreilicht Nov 15 '17 at 9:47
2

I'd ask myself what the user will want the program to do in most cases and make exactly that the default behaviour. This default behaviour should be triggered automatically when no option is specified. On the other hand if there is an option specified, nothing should be done by the command unless specified with an option.


Here's a counterexample of what I consider painfully poor programming:

avconv -i file.avi

outputs some information about your video file, -i sets the input file and as there's no output specified avconv takes it you just want the info.

avconv file.avi

overwrites your precious video without any warning or doing a backup, because avconv willfully takes the argument as the output file and writes to it no matter what, even if there's nothing to write.

I think you get the point.


Here's what I'd call intuitive. If the default behaviour is

  • both detect and blur:
    • command and
      command --detect --blur does detect and blur
    • command --detect does only detect
    • command --blur does only blur
  • just one, e.g. for detect:
    • command and
      command --detect does only detect
    • command --blur does only blur
    • command --detect --blur does detect and blur, if you feel like this is useful there's also command --detectblur as a shorthand for this

I'd also define the short options -d and -b so that users can call command -bd to set both options no matter what the default behaviour is.

  • Yes, the default is to do both. Thanks for providing the counterexample! – iFreilicht Nov 15 '17 at 9:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.