How to Check if a Program Exists from a Bash Script
When writing Bash scripts, you often need to verify that required programs or commands are available before attempting to use them. This prevents scripts from failing with "command not found" errors and allows you to provide helpful error messages or install missing dependencies.
This guide covers several reliable methods to check for program availability, along with their advantages and best practices for different scenarios.
Using the command Built-in (Recommended)
The most portable and reliable way to check if a program exists is using the command
built-in with the -v
option:
if command -v git &> /dev/null; then
echo "Git is installed"
else
echo "Git is not installed"
fi
The command -v
approach works because:
- It's a POSIX-compliant built-in available in all shells
- It checks the PATH for executables, shell built-ins, and functions
- It returns a non-zero exit code if the command isn't found
- It doesn't execute the command, just checks availability
Here's a practical function to check for multiple programs:
check_dependencies() {
local dependencies=("$@")
local missing=()
for cmd in "${dependencies[@]}"; do
if ! command -v "$cmd" &> /dev/null; then
missing+=("$cmd")
fi
done
if [ ${#missing[@]} -ne 0 ]; then
echo "Missing dependencies: ${missing[*]}"
return 1
fi
return 0
}
# Usage
if check_dependencies git curl jq; then
echo "All dependencies are available"
else
echo "Please install missing dependencies"
exit 1
fi
Using the which Command
The which
command is another common approach, but it has some limitations:
if which python3 &> /dev/null; then
echo "Python 3 is installed"
else
echo "Python 3 is not installed"
fi
However, which
has drawbacks:
- It's not available on all systems by default
- It doesn't detect shell built-ins or functions
- Some systems have different implementations with varying behavior
Use which
only when you specifically need to find the full path to an executable:
python_path=$(which python3)
if [ -n "$python_path" ]; then
echo "Python 3 found at: $python_path"
else
echo "Python 3 not found"
fi
Using the type Built-in
The type
built-in provides detailed information about commands:
if type git &> /dev/null; then
echo "Git is available"
type git # Shows what type of command it is
else
echo "Git is not available"
fi
The type
command can tell you whether something is:
- An executable file
- A shell built-in
- A function
- An alias
This is useful when you need to understand how a command will be interpreted:
check_command_type() {
local cmd="$1"
if type "$cmd" &> /dev/null; then
local cmd_type=$(type -t "$cmd")
case "$cmd_type" in
"file")
echo "$cmd is an executable file"
;;
"builtin")
echo "$cmd is a shell built-in"
;;
"function")
echo "$cmd is a function"
;;
"alias")
echo "$cmd is an alias"
;;
esac
return 0
else
echo "$cmd is not available"
return 1
fi
}
Checking for Specific Executables
Sometimes you need to check for a specific executable file, not just any command:
check_executable() {
local cmd="$1"
local path=$(command -v "$cmd")
if [ -n "$path" ] && [ -x "$path" ]; then
echo "$cmd is executable at $path"
return 0
else
echo "$cmd is not available as an executable"
return 1
fi
}
Checking Multiple Locations
For programs that might be installed in non-standard locations:
find_program() {
local program="$1"
local locations=(
"/usr/bin/$program"
"/usr/local/bin/$program"
"/opt/bin/$program"
"$HOME/bin/$program"
)
# First check PATH
if command -v "$program" &> /dev/null; then
command -v "$program"
return 0
fi
# Then check specific locations
for location in "${locations[@]}"; do
if [ -x "$location" ]; then
echo "$location"
return 0
fi
done
return 1
}
# Usage
if program_path=$(find_program "custom-tool"); then
echo "Found custom-tool at: $program_path"
else
echo "custom-tool not found"
fi
Version Checking
Often you need to verify not just that a program exists, but that it meets version requirements:
check_git_version() {
if ! command -v git &> /dev/null; then
echo "Git is not installed"
return 1
fi
local version=$(git --version | awk '{print $3}')
local required="2.20.0"
if [ "$(printf '%s\n' "$required" "$version" | sort -V | head -n1)" = "$required" ]; then
echo "Git version $version meets requirements"
return 0
else
echo "Git version $version is too old (required: $required)"
return 1
fi
}
Creating a Comprehensive Dependency Checker
Here's a complete function that combines all the best practices:
#!/bin/bash
check_program() {
local program="$1"
local required_version="$2"
local install_hint="$3"
# Check if program exists
if ! command -v "$program" &> /dev/null; then
echo "❌ $program is not installed"
if [ -n "$install_hint" ]; then
echo " Install with: $install_hint"
fi
return 1
fi
echo "✅ $program is available"
# Check version if specified
if [ -n "$required_version" ]; then
case "$program" in
"git")
version=$(git --version | awk '{print $3}')
;;
"python3")
version=$(python3 --version | awk '{print $2}')
;;
"node")
version=$(node --version | sed 's/v//')
;;
*)
echo " (Version check not implemented for $program)"
return 0
;;
esac
if [ "$(printf '%s\n' "$required_version" "$version" | sort -V | head -n1)" = "$required_version" ]; then
echo " Version $version meets requirement (>= $required_version)"
else
echo " ❌ Version $version is too old (required: >= $required_version)"
return 1
fi
fi
return 0
}
# Main dependency check
main() {
echo "Checking dependencies..."
local all_good=true
check_program "git" "2.20.0" "sudo apt install git" || all_good=false
check_program "curl" "" "sudo apt install curl" || all_good=false
check_program "jq" "" "sudo apt install jq" || all_good=false
check_program "python3" "3.8.0" "sudo apt install python3" || all_good=false
if [ "$all_good" = true ]; then
echo ""
echo "✅ All dependencies are satisfied!"
return 0
else
echo ""
echo "❌ Some dependencies are missing or outdated"
return 1
fi
}
# Run the check
if [ "${BASH_SOURCE[0]}" = "${0}" ]; then
main "$@"
fi
Best Practices
- Use
command -v
for most cases - It's the most portable and reliable method - Suppress output with
&> /dev/null
- Keep your checks clean - Provide helpful error messages - Tell users how to install missing programs
- Check early in your script - Fail fast if dependencies are missing
- Consider version requirements - Some scripts need specific versions
- Group dependency checks - Check all requirements before starting work
Checking for program availability is a crucial part of writing robust Bash scripts. Using the right method for your specific needs ensures your scripts work reliably across different systems and provide helpful feedback when requirements aren't met.
Found an issue?