LearnLinux FoundationsBash Shell Environment

which

which - a hands-on Linux lab on a real virtual machine.

Turn a command name into the real file that runs it with which. Locate ls and interpreters for a script first line, use -a to see every copy on PATH and which one wins, and learn the key limitation: which sees only files, never builtins like cd, which is why type exists. Paths can vary by machine, so the drills teach the moves and the shape.

Every command you run is a program, and every program is a file sitting somewhere on the disk. When you type ls, your shell does not magically know what to do. It goes hunting through a list of folders, finds a file called ls, and runs it. You have been trusting that machinery blindly. This lesson shows you the file it finds.

The command is which. You hand it a name, it hands you back the full path of the program that would run. It is the difference between knowing a person's name and knowing their street address.

The black boxes below are a practice terminal: a safe sandbox that checks only the one command each step teaches, so you cannot break anything. which reports paths from your machine's real PATH, so the exact folder can vary. The outputs shown here are one real capture, kept as an example, and marked where your machine may read differently. On the live machine at the end of the module, you run which for real.

which searches your PATH for an executable file and prints where it found it. Two terms, defined once. An executable is a file the system is allowed to run as a program. Your PATH is a list of folders, kept in a variable, that the shell searches whenever you type a command name.

So which NAME means: walk the PATH folders in order, and the moment you find a runnable file called NAME, print its full path and stop. Start with a command you know by heart. Ask where ls lives:

which ls

prompt: student@linuxcamp:~$ answer: which ls output: /usr/bin/ls hint: Type which, a space, then the command name: which ls

One line, one path. which told you that when you type ls, the shell runs the file at /usr/bin/ls. On some machines you might see /bin/ls instead. On modern Debian those are the same file, because /bin is just a shortcut pointing into /usr/bin, so the path resolves to /usr/bin/ls. Either way the lesson holds: which turned a bare name into a real, findable file on disk.

Here is where which earns its keep in real work. When you write a script, its very first line points at an interpreter, like #!/usr/bin/python3. To write that line correctly you need to know where python3 actually lives. You do not guess. You ask which.

Point it at the Python interpreter:

which python3

prompt: student@linuxcamp:~$ answer: which python3 output: /usr/bin/python3 hint: Same which, then the interpreter name: which python3

The path /usr/bin/python3 is this machine's answer. Yours may read differently if Python is installed somewhere else, and that is exactly the point: you ask which precisely because you should not assume the path. The MOVE is what stays the same everywhere, which <interpreter> gives you the exact path to put in a script's first line. The same trick works for which bash, which on this machine prints /usr/bin/bash.

By default which stops at the FIRST match and says nothing about the rest. Usually that is what you want. But sometimes a command misbehaves because an older copy is hiding earlier in your PATH and winning. To see every copy, add -a. The a stands for all: keep searching past the first hit and print every match, one per line.

Ask for every python3 on the PATH:

which -a python3

prompt: student@linuxcamp:~$ answer: which -a python3 output: /usr/bin/python3 hint: Add the -a flag between which and the name: which -a python3

On this machine there is only one python3, so -a prints a single line, the same as before. But when two versions ARE installed, which -a python3 prints both, in PATH order, top to bottom. The first line is the one that actually runs; the lines below it are the copies being shadowed. That top-to-bottom order is the whole value of -a: it shows you not just where a command is, but which duplicate is winning and which are losing.

Now the single most important thing to understand about which, and the reason it is not the whole story. which only finds real executable FILES on your PATH. It knows nothing about builtins (commands baked into bash itself, not stored as files), nothing about aliases, nothing about shell functions.

cd is a builtin. It is part of bash, not a file on disk. Watch what happens when you ask which where cd lives:

which cd

prompt: student@linuxcamp:~$ answer: which cd output: hint: Type which and the builtin name, and read the silence: which cd

Nothing printed. That blank is not a bug and cd is not broken; you use cd constantly and it works fine. which printed nothing because cd is a builtin, and which searches only for files on the PATH. There is no file called cd for it to find. Behind that silence, which also exits with a failure code, its quiet way of saying it came up empty. Remember this shape. An empty line from which means one of two things: the command is a builtin, an alias, or a function, or it is simply not installed.

This is exactly why the previous lesson taught type. Where which sees only files, type sees everything: run type cd and it tells you plainly cd is a shell builtin, the answer which could not give. So the two split the work. which answers WHERE an executable file is on disk, which is perfect for interpreter paths and hunting duplicate versions. type answers WHAT a name really is, builtin or alias or function or file. When which goes silent, type is the command that tells you why.

Scaffolding off. No command is printed this time. You have every piece you need.

You are about to write a Python script, and its first line must point at the exact place python3 is installed on this machine. You do not want to guess the path, and you do not care about any other command. Ask the machine for the one full path to python3.

prompt: student@linuxcamp:~$ answer: which python3 output: /usr/bin/python3 hint: The command that turns a name into its file path, followed by the interpreter name. Think which, then python3.

That is the everyday move a working engineer makes before writing a script's first line. which python3 walked the PATH, found the interpreter file, and handed you its full path, ready to drop after the #!. Your own path may read differently, but the SHAPE, one name in, one full path out, is what you will see on any machine, and the command is exactly what an engineer types. You recalled it from memory, which is the same recall the real machine will ask of you.

You earned this cheat sheet. Every row is a form of which you just ran:

The one habit to keep: when which prints a path, you have a real file you can trust. When which prints nothing, do not panic and do not assume the command is broken. It is telling you either the command is a builtin, an alias, or a function, or it is not installed. Reach for type to learn which.

which and type are partners, not rivals. Reach for which when you want a clean file path to paste, into a script's #! line or a config file. Reach for type when a command surprises you and you need to know what it really is. Path to paste: which. Identity to understand: type.

The practice terminal has shown you what which is for: turning a command name into the real file that runs it. You located ls, found the python3 interpreter for a script's first line, used -a to see every copy of a command, and watched which fall silent on the builtin cd, the limitation that sends you to type. Every one of those you typed yourself.

The Bash Environment module ends with one real Linux machine, the Bash Environment capstone mission, and that is where you use which for real. A VM boots just for you, with its own live PATH and its own installed programs. It hands you objectives that use exactly what you practiced across this module: variables, export, PATH, and knowing which file the shell truly runs. One difference from here: the mission shows no commands. You read the objective, you recall the command, you type it. That recall is what makes it stick.

Finish the other Bash Environment lessons, then go locate real programs on a real PATH for yourself.

Practice which in a real Linux terminal at The Linux Camp. Progress is verified automatically as you type commands on the machine.