When writing shell scripts, it's common to install dependencies before executing a command. However, running an install command every timeā€”even when the dependency is already availableā€”can slow down your workflow. A better approach is to check if the command exists before attempting an installation. This simple optimization can make scripts more efficient and avoid unnecessary package installations.

Consider a script that installs jq, a popular command-line JSON processor, and then processes a JSON file:

brew install jq && jq . data.json

This script ensures that jq is installed before running it, but thereā€™s a flaw: every time the script runs, brew install jq executesā€”even if jq is already installed. While Homebrew might not reinstall jq if it's already present, the command still takes time to check the package status.

A more efficient approach is to check whether jq is installed before attempting to install it. Here's how you can do that:

command -v jq >/dev/null 2>&1 || brew install jq && jq . data.json

How it works:

  1. command -v jq checks if jq is available in the system.
  2. >/dev/null 2>&1 suppresses output and errors, preventing unnecessary messages.
  3. || brew install jq only runs brew install jq if the previous check fails (meaning jq is not installed).
  4. && jq . data.json ensures that jq runs only after itā€™s confirmed to be installed.

This approach works for various package managers and commands. Hereā€™s how you might use it with npm:

command -v eslint >/dev/null 2>&1 || npm install -g eslint && eslint src/

Or with pip for Python packages:

command -v black >/dev/null 2>&1 || pip install black && black .

By integrating this pattern into your shell scripts, you can improve efficiency while ensuring dependencies are installed only when necessary.