Skip to main content

How to Check if Command Exists

• 2 min read
bash command checking existence testing error handling portability

Quick Answer: Check if Command Exists in Bash

To check if a command exists, use command -v commandname &>/dev/null. If it returns true, the command exists. Example: if command -v python &>/dev/null; then … This is the most portable and reliable method.

Quick Comparison: Command Checking Methods

MethodSyntaxReliabilityPortabilityBest For
command -vcommand -v cmdExcellentUniversalMost cases
typetype cmdVery goodMost shellsShell builtins
whichwhich cmdGoodMost systemsQuick check
hashhash cmdGoodBash onlyCached commands

Bottom line: Use command -v for maximum portability and reliability.


Why Check if a Command Exists?

Before using a command in a script, you should verify it exists on the system. Not all systems have the same tools installed. For example, some Linux distributions might have curl but not wget, or vice versa. Checking for command availability prevents confusing “command not found” errors and lets you handle missing tools gracefully.

The command builtin is the most reliable way to check if a command exists:

#!/bin/bash

# Check if python is available
if command -v python &>/dev/null; then
  echo "Python is installed"
else
  echo "Python is not installed"
fi

# Check if docker exists
if command -v docker &>/dev/null; then
  echo "Docker is available"
else
  echo "Docker is not available"
fi

The -v flag returns the path to the command if it exists, or nothing if it doesn’t. We redirect output to /dev/null to suppress the output and only use the exit code.

Practical Example: Fallback Commands

Here’s a real-world scenario - trying multiple tools and falling back to alternatives:

#!/bin/bash

# Try to use the best available option for JSON pretty-printing
pretty_json() {
  if command -v jq &>/dev/null; then
    # Best option - jq is fast and powerful
    jq '.' <<< "$1"
  elif command -v python &>/dev/null; then
    # Fallback to Python
    python -m json.tool <<< "$1"
  elif command -v python3 &>/dev/null; then
    # Another Python option
    python3 -m json.tool <<< "$1"
  else
    # Last resort - just output as-is
    echo "$1"
  fi
}

# Usage
pretty_json '{"name": "John", "age": 30}'

Checking Multiple Commands

When your script requires several tools, check them all at startup:

#!/bin/bash

# Required commands for the script to work
REQUIRED_COMMANDS=("curl" "grep" "sed" "awk")

# Check if all required commands exist
for cmd in "${REQUIRED_COMMANDS[@]}"; do
  if ! command -v "$cmd" &>/dev/null; then
    echo "ERROR: Required command '$cmd' is not installed"
    exit 1
  fi
done

echo "All required commands are available"
# Continue with script...

This is much cleaner than checking each command individually with separate if statements.

Real-World Example: Package Manager Detection

Detect which package manager is available:

#!/bin/bash

install_package() {
  local package="$1"

  if command -v apt-get &>/dev/null; then
    echo "Using apt-get..."
    sudo apt-get update
    sudo apt-get install -y "$package"
  elif command -v yum &>/dev/null; then
    echo "Using yum..."
    sudo yum install -y "$package"
  elif command -v brew &>/dev/null; then
    echo "Using brew..."
    brew install "$package"
  else
    echo "ERROR: No supported package manager found"
    return 1
  fi
}

# Usage
install_package "git"

Getting the Command Path

Sometimes you want the actual path to the command:

#!/bin/bash

# Get the full path to a command
if cmd_path=$(command -v python3); then
  echo "Python 3 is located at: $cmd_path"
else
  echo "Python 3 not found"
fi

# This could output: /usr/bin/python3

Alternative: Using which

While which also checks for commands, command is preferred because it’s more portable:

# Less reliable - doesn't work in all contexts
which python

# More reliable - recommended
command -v python

Checking for Specific Command Features

Sometimes you need a specific version or capability:

#!/bin/bash

# Check for grep and ensure it supports -E (extended regex)
if command -v grep &>/dev/null && grep -E . &>/dev/null; then
  echo "grep with extended regex support is available"
fi

# Check for bash version 4 or higher
if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then
  echo "Bash 4+ is available"
else
  echo "Bash 3 or older - some features unavailable"
fi

Practical Example: System Diagnostic Script

#!/bin/bash

echo "=== System Diagnostic ==="
echo ""

# List of optional tools and what they do
TOOLS=("curl:Network requests" "wget:Downloading files" "git:Version control" "docker:Containerization" "node:JavaScript runtime")

for tool_info in "${TOOLS[@]}"; do
  tool="${tool_info%:*}"
  description="${tool_info#*:}"

  if command -v "$tool" &>/dev/null; then
    echo "âś“ $tool - $description"
  else
    echo "âś— $tool - NOT INSTALLED ($description)"
  fi
done

Output:

=== System Diagnostic ===

âś“ curl - Network requests
âś— wget - NOT INSTALLED (Downloading files)
âś“ git - Version control
âś“ docker - Containerization
âś— node - NOT INSTALLED (JavaScript runtime)

Important Notes

  • Use command -v in portable scripts
  • The &>/dev/null redirects both stdout and stderr, suppressing output
  • Exit code 0 means the command exists, non-zero means it doesn’t
  • Always quote command names: command -v "$cmd" not command -v $cmd
  • command is a shell builtin - it’s always available

Quick Reference

# Check if command exists and continue if it does
if command -v docker &>/dev/null; then
  docker ps
fi

# Check and exit if command doesn't exist
if ! command -v gcc &>/dev/null; then
  echo "GCC compiler not found"
  exit 1
fi

# Get the path to a command
PATH_TO_CMD=$(command -v python3)

# Check if one of several commands exists
for cmd in python python3 python2; do
  if command -v "$cmd" &>/dev/null; then
    echo "Found: $cmd"
    break
  fi
done

Summary

Checking if commands exist before using them makes your scripts more robust and portable. Use command -v to verify tools are available, provide fallbacks for alternatives, and give clear error messages when required tools are missing. This is especially important when distributing scripts across different systems.