Subcommands

This article is about creating applications with user subcommands, such as docker subcommand that will call docker-subcommand, for applications that do not support it by default.

Many modern applications support subcommands as their first argument. For example, one may invoke git status or docker images.

Some of these tools allow arbitrary user-defined subcommands. This is the case with git: when an unknown subcommand is issued, git searches the $PATH for an executable whose name is prefixed with git-. For instance, invoking git hello will execute the first git-hello binary found in the search path.

By contrast, commands such as docker do not support arbitrary user-defined subcommands.

The following script enables users to achieve similar subcommand resolution behavior with commands that do not natively support it, such as docker or pgp.

Assuming that $PATH includes $HOME/bin, create the file named _subcommand in $HOME/bin and mark it as executable.

wget https://blog.cappysan.dev/scripts/snippets/_subcommand -O ${HOME}/bin/_subcommand
chmod +x ${HOME}/bin/_subcommand

For every application that supports subcommands, you can now create a symlink from $HOME/bin/example to the file _subcommand to have it support user subcommands.

For example, to add user subcommands to docker, create a docker file that is a symlink to _subcommand:

ln -vs -T _subcommand ${HOME}/bin/docker

You can now create arbitrary commands in $HOME/bin with the prefix docker-.

One such application could be docker upgrade that downloads the most recent docker image for all images that have a tag. To do this, create an executable script named docker-upgrade in $HOME/bin/ with the following content:

#!/usr/bin/env bash
exec docker images --format table | tail -n '+2' | grep -v '<none>' | awk -F' ' '{ print $1 }' | xargs -n1 docker pull

You can now use this technique for any application that supports subcommands. If the prefixed application is not found in $PATH, the normal subcommand will be called.

Note

If the new command you created is not found, it might be useful to issue a hash -r to reset the application location cache.