which Command in Linux with Examples

The which command displays the full path to an executable that your shell would run when you type a command name. This helps you identify which program version runs, verify that a tool exists in your PATH, and ensure scripts reference the correct binary. By the end of this guide, you will understand how to locate executables, handle multiple matches, recognize shell built-in limitations, and choose the right lookup tool for different situations.

Understanding the which Command

When you type a command like ls or python3, your shell searches directories listed in the PATH environment variable until it finds a matching executable. The which command performs this same search and reports the path it would use. Understanding this behavior helps you troubleshoot path-related issues and verify installations.

You will find this command useful in several situations. System administrators often need to verify that a specific tool version remains accessible. Script writers use which to confirm that required commands exist before running. Developers working with multiple language versions rely on it to check which interpreter runs by default.

Implementation Differences

Linux distributions ship two main implementations of which, and these differences determine which options you can use.

GNU which (Fedora, RHEL, Arch, openSUSE, Gentoo)

  • Supports extended options like --skip-dot, --show-tilde, and alias handling
  • Prints explicit error messages when a command is not found
  • Supports --version to check the implementation

Minimal which (Debian, Ubuntu, and derivatives)

  • Supports only -a (show all matches) and -s (silent mode)
  • Returns silently with exit code 1 when a command is not found
  • Does not support --version or other GNU options

Basic Syntax

The fundamental structure is straightforward:

which command_name

For example, to find the location of ls:

which ls

On most Linux systems, this returns:

/usr/bin/ls

The output indicates that running ls executes the binary at /usr/bin/ls.

Available Options

The options available depend on your distribution’s implementation.

Universal option (all implementations)

  • -a: Print all matching executables in PATH, not just the first one

Minimal which only (Debian, Ubuntu, and derivatives)

  • -s: Silent mode; return exit code only without printing paths (useful for scripts)

GNU which only (Fedora, RHEL, Arch, openSUSE, Gentoo)

  • --version: Display version information
  • --skip-dot: Skip directories in PATH that start with a dot
  • --skip-tilde: Skip directories in PATH that start with a tilde
  • --show-dot: Do not expand a dot to the current directory in output
  • --show-tilde: Output a tilde for HOME directory (non-root users)
  • -i or --read-alias: Read alias definitions from stdin

If you attempt to use GNU-specific options on Debian or Ubuntu, you will see an error like Illegal option -- because the minimal implementation does not recognize them.

Practical Examples

Locate Common Utilities

Finding the path to text-processing tools helps when building scripts that need absolute paths:

which grep
/usr/bin/grep

Similarly, you can locate archive and stream-editing utilities:

which tar awk
/usr/bin/tar
/usr/bin/awk

When querying multiple commands, which prints each path on a separate line in the order you specified. For related text-processing tasks, consider our grep command guide or sed command tutorial.

Verify Software Installation

After installing software, you can confirm your PATH includes it:

which python3

When Python 3 exists and appears in your PATH, you will see:

/usr/bin/python3

When the command produces no output and returns to the prompt, the executable either does not exist or does not appear in your PATH. On Debian and Ubuntu systems, the absence of output indicates the command was not found. In contrast, GNU which on Fedora explicitly states this:

which: no python3 in (/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin)

Display All Matches with -a

The -a option reveals all matching executables across your entire PATH. This option proves essential when multiple versions of a program exist:

which -a ls
/usr/bin/ls
/bin/ls

Both paths point to the same binary in this case because /bin typically links to /usr/bin on modern systems (called “merged /usr”). The first path listed is the one your shell would execute.

This option becomes more useful when you have installed multiple versions of software. For example, if you compiled Python locally alongside the system version:

which -a python3
/usr/local/bin/python3
/usr/bin/python3

The first path listed is the one your shell would execute. In this case, the locally compiled version in /usr/local/bin takes priority. Combining this with --version confirms which version runs by default:

$(which python3) --version
Python 3.x.x

Check Shell Location

System administrators often need to verify which shell is being used:

which bash
/usr/bin/bash

This path is commonly used in script shebang lines (#!/usr/bin/bash) to ensure the correct interpreter runs the script.

Understanding Exit Codes

The which command returns specific exit codes that scripts can use for conditional logic:

  • Exit code 0: All specified commands were found
  • Exit code 1: One or more commands were not found
  • Exit code 2: Invalid option specified (GNU which only)

You can use these exit codes in scripts to check whether a command exists before attempting to use it:

if which docker > /dev/null 2>&1; then
    echo "Docker is installed at $(which docker)"
else
    echo "Docker is not installed"
fi

The redirection to /dev/null suppresses output, and the script uses only the exit code for the conditional check. For more shell scripting techniques, see our bash wait command guide.

Shell Built-ins vs External Commands

Some commands like cd, echo, and pwd exist both as shell built-ins and as external executables. However, the which command only searches for files in PATH directories, so it cannot detect built-ins.

which echo
/usr/bin/echo

This output shows the external /usr/bin/echo binary, but when you type echo in bash, the shell actually uses its built-in version for performance reasons. To see what your shell would actually execute, use the type command instead:

type echo
echo is a shell builtin

For commands that exist only as built-ins with no external equivalent, which returns nothing:

which cd

Running this produces no output because cd is purely a shell built-in. The type command correctly identifies it:

type cd
cd is a shell builtin

Alternatives to which

While which works well for finding executables, several other tools offer different capabilities or better portability across systems.

The command -v Approach

The POSIX-compliant command -v is available in all shells and does not require external packages:

command -v ls
/usr/bin/ls

Unlike which, this approach also works for shell functions and built-ins, making it more versatile. Many shell scripting guides recommend command -v over which because every POSIX-compliant system includes it, even minimal containers where which might not exist.

The type Command

The type shell built-in shows how your shell interprets a command, distinguishing between aliases, functions, built-ins, and external commands:

type ls
ls is /usr/bin/ls

If ls were aliased (common on many systems), type would show the alias definition instead. To see all definitions, use type -a:

type -a echo
echo is a shell builtin
echo is /usr/bin/echo
echo is /bin/echo

This output shows that bash uses its built-in echo by default, with two external binaries available as fallbacks. The order matters because the shell tries each one from top to bottom.

Comparison Table

ToolFinds Built-insFinds AliasesPOSIX PortableBest Use Case
whichNoNoNoQuick external binary lookup
command -vYesYesYesPortable scripts, minimal systems
typeYesYesYesUnderstanding shell behavior

Advanced Usage

Verify Developer Tools

Before compiling software, you should verify that your system has the necessary build tools:

which gcc make cmake

If all tools are installed, you will see their paths. Missing tools produce no output on Debian and Ubuntu, or explicit error messages on Fedora. Consequently, this quick check helps identify what needs to be installed before starting a build process.

Locate Custom Scripts

Custom scripts stored in ~/bin or ~/.local/bin become accessible when you include those directories in your PATH. Verify accessibility with:

which myscript

When the script appears in your PATH and has execute permission, you will see its full path. Otherwise, check that the directory appears in PATH and that the script has execute permission. You can set execute permission with chmod +x myscript. For a complete overview of permission management, see our chmod command guide.

Priority in PATH

When the same command exists in multiple PATH directories, the shell uses the first match. The which command shows you which version takes priority:

which python3

If you have installed Python locally to /usr/local/bin and that directory appears before /usr/bin in your PATH, the local version runs by default. Use which -a python3 to see all available versions and their order.

Troubleshooting

Command Not Found But Installed

If you installed software but which returns nothing, the executable likely does not exist in your PATH. First, check the installation location, then verify your PATH includes that directory:

echo $PATH

Common locations that might not appear in PATH by default include /usr/local/bin, /opt/program/bin, and ~/.local/bin. If needed, add the directory to your PATH in ~/.bashrc:

export PATH="$PATH:/path/to/new/directory"

After editing, reload your shell configuration with source ~/.bashrc or open a new terminal.

Illegal Option Error

If you see Illegal option -- when using options like --version, you are using the minimal which implementation (Debian, Ubuntu, and derivatives), which only supports -a and -s. For extended functionality, use type or command -v instead, as these are built into your shell.

Hash Table Caching

Bash caches command locations for performance. If you install a new version of a command, your shell might still use the cached path. To view the current cache, run:

hash
hits    command
   3    /usr/bin/which
   1    /usr/bin/grep

Clear the cache with:

hash -r

After running this command, both which and the command itself will search PATH fresh. You can verify the cache is empty by running hash again:

hash
hash: hash table empty

Conclusion

The which command provides a quick way to locate executables in your PATH, verify installations, and identify which version of a program runs by default. For scripts needing maximum portability, consider using command -v instead. Similarly, use type when you need to understand how your shell interprets a command, including aliases and built-ins. Together, these tools give you complete visibility into where your commands come from and which versions your shell will execute.

Leave a Comment