LearnLinux FoundationsBash Shell Environment

command

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

Reach past aliases and functions to the real tool with command. Run the genuine program with command CMD, ask how a name resolves with command -v (the portable, script-safe alternative to which), read the verbose form with command -V, and use command -v as the existence test scripts rely on. Paths vary by machine, so the drills teach the behaviour and the forms.

You have spent this module bending the shell to your will. You made alias shortcuts, you defined shortcuts that stand in for longer commands, you watched type tell you what a name really points at. But every one of those tools you built has a side effect nobody warns you about: they can quietly change what a plain command name does.

Picture it. You set alias ls="ls --color=auto" weeks ago and forgot. Now you write a script that runs ls, and you get behaviour you did not expect, because the name ls no longer means the real ls. It means YOUR version. So here is the question this lesson answers: when you type a name, how do you force the shell to run the REAL program, ignoring every shortcut you or the system layered on top? The answer is a single word, command.

The black boxes in this lesson are a practice terminal: a safe sandbox that only checks the one command each step teaches, so you cannot break anything. Where an output shows a full path like /usr/bin/ls, that path is this machine's; on yours it may sit elsewhere. The BEHAVIOUR, not the exact path, is the lesson, and the behaviour is the same everywhere.

command is a shell builtin, a tool baked into bash itself rather than a separate program on disk. Its job is narrow and useful: it runs the command you name while ignoring any alias or shell function that shares that name. An alias is a shortcut you defined with alias. A function is a small named block of shell code. Both can shadow a real command by reusing its name. command steps around them and reaches the real tool underneath.

Think of it like asking for the manufacturer's part, not the aftermarket one somebody bolted on. You typed ls for years; somewhere along the way an alias wrapped it. command ls peels that wrapper off and hands you the plain, factory ls.

First, prove the shadow exists. This practice machine already has one alias set for you: ls is aliased to add colour. Ask the shell what ls currently means. type reports how a name resolves, and right now it will tell you ls is an alias, not a plain program:

type ls

prompt: student@linuxcamp:~$ answer: type ls output: ls is aliased to `ls --color=auto' hint: Type the word type, a space, then ls: type ls

So the name ls does not point straight at the real program. It points at an alias that quietly adds --color=auto. Every time you type ls, you are really running ls --color=auto. Most days that is harmless. But it means ls is not neutral, and inside a script that assumption can bite. Next you reach past the alias and run the real thing.

To run the genuine, un-aliased program, put command in front of it. command ls tells bash: forget any alias or function named ls, find the real ls program, and run that. The colour wrapper is ignored. You get the plain listing, exactly as the un-aliased ls would print it.

Run it now and read the plain, un-aliased output:

command ls

prompt: student@linuxcamp:~$ answer: command ls output: Desktop Documents Downloads notes.txt projects hint: Put the word command in front of ls: command ls

The names in that listing are this practice machine's files; your own directory holds different names. What matters is that command ls ran the real ls with the alias stripped off. The alias is still set, you did not delete it, you simply stepped around it for this one run.

That listing came from the real ls, not the coloured alias. command did exactly one thing: it looked past the alias named ls and ran the actual program. The alias still exists for your next bare ls. This is the whole point of command CMD: a one-shot guarantee that you are running the factory tool, no matter what shortcuts are layered on the name. In a script, that guarantee is gold, because you cannot know what aliases the person running it has set.

command has a second job, and it is the one you will type most. The -v flag does not RUN anything. It prints how a name would resolve: where the shell would go if you typed that name. For a normal program it prints the full path on disk. Ask it about grep:

command -v grep

prompt: student@linuxcamp:~$ answer: command -v grep output: /usr/bin/grep hint: command, then a space, -v, then the name grep: command -v grep

That path, /usr/bin/grep, is where this machine keeps grep. On yours it might live somewhere else. What is stable everywhere is the SHAPE of the answer: command -v of a real program prints the one path the shell would run. Read the path, not the exact folder.

command -v grep told you the exact program the shell would launch for grep, the full path on disk. You may have met which doing a similar job. command -v is the one to remember. It is a shell builtin, it is defined by the POSIX standard, and it works the same way in every script on every system. which is a separate program that is not always installed and does not always behave the same. When a script needs to ask how a name resolves, command -v is the portable, safe choice.

Not every name is a program on disk. Some, like cd, are builtins baked into bash, the same as command itself. There is no file on disk to point at. So command -v cd cannot print a path. Instead it prints the name back, plain, telling you: this one is a builtin, not a file. Try it:

command -v cd

prompt: student@linuxcamp:~$ answer: command -v cd output: cd hint: Same command -v as before, then the builtin name cd: command -v cd

One bare word: cd. No path, because cd is not a file. When command -v prints just the name you handed it, that is your signal the name is a shell builtin living inside bash, with nothing on disk to point to. So -v speaks two dialects: a full path for a real program like grep, and a bare word for a builtin like cd. Both are it answering the same question, how would this name resolve.

The lowercase -v gives you the bare answer, a path or a name. The uppercase -V gives you the same fact wrapped in a full sentence, spelling out what the name is. It is the human-readable version. Ask it about ls, the aliased name from earlier. Because you are running command, it reports what ls really is underneath, the real program:

command -V ls

prompt: student@linuxcamp:~$ answer: command -V ls output: ls is /usr/bin/ls hint: This time the V is uppercase: command -V ls

Again the path /usr/bin/ls is this machine's, and yours may differ. Note the case: lowercase -v prints the bare path or name, uppercase -V prints the full sentence ls is /usr/bin/ls. Same fact, two levels of detail. Mixing up the case is the most common slip here, so read it back before you press Enter.

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

Here is the real-world reason command -v matters most. Before a script uses a tool, it should check the tool is actually installed, and command -v is exactly how. When you hand command -v a name that does not exist, it prints NOTHING and quietly reports failure, which is precisely how a script tests "is this here?". Ask it about a program named grep, and prove to yourself you can call up how a real tool resolves from memory.

prompt: student@linuxcamp:~$ answer: command -v grep output: /usr/bin/grep hint: You want how a name resolves, not the verbose sentence. Think command, then the lowercase resolve flag, then grep.

That is the move a real script makes. command -v grep printed the path, which means grep exists and the script can safely use it. Hand the same flag a name that is NOT installed and you get an empty line and a quiet failure signal instead, which is how a script decides to stop or take another path. Your path will differ from this machine's, but the behaviour, a path when it exists, nothing when it does not, is identical everywhere. You recalled the flag and the shape 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 command you just ran:

The one behaviour to carry with you: command reaches past aliases and functions to the real tool, and command -v NAME is the portable, script-safe way to ask how a name resolves or whether it exists at all.

command steps around aliases and functions, but it does NOT step around your PATH, the list of folders where the shell hunts for programs. If a tool is not in any PATH folder, command cannot conjure it. That is why command -v printing nothing means the tool is genuinely not reachable, not merely hidden behind a shortcut.

The practice terminal has shown you both jobs command does. You bypassed a live alias to run the real ls. You read how grep and the builtin cd resolve with -v. You saw the verbose -V sentence, and you used command -v as the existence test a real script relies on. 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 run command for real. A VM boots just for you, with its own aliases, its own PATH, and its own tools installed. It hands you objectives that use exactly what you practiced across this module: aliases, variables, PATH, and the tools that read them back, command among them. 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 find the ground truth on a real machine for yourself.

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