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.