Linux CLI 7 🐧 Commands type, which
What are commands?
When you type a command in the shell, several things can happen behind the scenes. The type and which commands help you identify what kind of command you’re running and where it lives on the system.
Overview
ls /usr/bin
type cd
type mv
type cd mv ls
which ls
which blahblah
which -a python
which ls python
| Command | Description |
|---|---|
ls /usr/bin | List all executable files in /usr/bin |
type cd | Show what kind of command cd is |
type mv | Show what kind of command mv is |
type cd mv ls | Check multiple commands at once |
which ls | Locate the executable for ls |
which blahblah | Returns nothing if not found |
which -a python | Show all matches in PATH |
which ls python | Check multiple commands |
What Are Commands?
In Linux, a “command” can be one of several things:
| Type | Description | Example |
|---|---|---|
| External command | An executable file in /usr/bin, /bin, etc. | ls, mv, grep |
| Shell builtin | A command built into the shell itself | cd, echo, pwd |
| Alias | A shortcut for another command | ll → ls -la |
| Shell function | A custom function defined in the shell | mkcd() → mkdir + cd |
| Keyword | A reserved word in the shell language | if, for, while |
Most commands you use are files in /usr/bin — but not all!
Where Commands Live
ls /usr/bin
This shows all executable files in /usr/bin — but that’s just one of many directories where commands live.
Common directories for executables:
| Directory | Purpose |
|---|---|
/bin | Essential user commands (often symlink to /usr/bin) |
/usr/bin | Most user commands |
/sbin | System administration commands |
/usr/sbin | Non-essential system commands |
/usr/local/bin | Locally installed software |
~/.local/bin | User-installed binaries |
~/bin | Your personal scripts |
The PATH variable determines where the shell looks for commands:
echo $PATH
# /usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/home/kronos/.local/bin
The shell searches these directories in order — the first match wins.
The type Command
The type command identifies what kind of command you’re running.
type cd
type mv
type cd mv ls
| Command | Description |
|---|---|
type cd | Show what cd is (shell builtin) |
type mv | Show what mv is (external command) |
type cd mv ls | Check multiple commands at once |
Examples
$ type cd
cd is a shell builtin
$ type mv
mv is /usr/bin/mv
$ type ls
ls is aliased to `ls --color=auto'
$ type pwd
pwd is a shell builtin
$ type for
for is a shell keyword
Multiple commands at once:
$ type cd mv ls pwd
cd is a shell builtin
mv is /usr/bin/mv
ls is aliased to `ls --color=auto'
pwd is a shell builtin
Exit codes:
$ type cd && echo "found"
cd is a shell builtin
found
$ type nonexistent 2>/dev/null
$ echo $?
1
Output types you’ll see:
| Output | Meaning |
|---|---|
X is a shell builtin | Built into the shell |
X is /path/to/X | External executable at that path |
X is aliased to 'command' | Alias |
X is a shell function | Function defined in shell |
X is a shell keyword | Reserved word |
type: X: not found | Command doesn’t exist |
Options for type:
| Option | Description |
|---|---|
-a | Show all matches (not just the first) |
-t | Show only the type: alias, keyword, function, builtin, file |
-p | Show the path (nothing if not a file) |
-P | Force PATH search (even for builtins) |
Examples with options:
# -a shows all matches
$ type -a ls
ls is aliased to `ls --color=auto'
ls is /usr/bin/ls
ls is /bin/ls
# -t shows just the type
$ type -t cd
builtin
$ type -t ls
alias
$ type -t mv
file
$ type -t for
keyword
# -p shows only the path
$ type -p mv
/usr/bin/mv
$ type -p cd
# (empty — cd is not a file)
# -P forces PATH lookup
$ type -P cd
/usr/bin/cd # (the external cd binary, if it exists)
Why type is useful:
- Understanding how the shell interprets commands
- Debugging — know why a command behaves unexpectedly
- Safety — verify what a command will actually do (e.g., an alias that shadows a real command)
- Learning — discover which commands are builtins vs external
The which Command
The which command locates the executable file for a given command — but only for external commands.
which ls
which blahblah
which -a python
which ls python
| Command | Description |
|---|---|
which ls | Show path to ls |
which blahblah | Show nothing if not found |
which -a python | Show all paths to python |
which ls python | Check multiple commands |
Examples
$ which ls
/usr/bin/ls
$ which mv
/usr/bin/mv
$ which blahblah
# (no output — not found)
$ which ls python
/usr/bin/ls
/usr/bin/python3
The -a option — find all matches:
$ which -a python
/usr/bin/python
/usr/local/bin/python
This is useful when multiple versions of a program are installed — you can see which one will run by default (the first one in $PATH).
Exit codes:
$ which ls
/usr/bin/ls
$ echo $?
0
$ which nonexistent
$ echo $?
1
What which Does NOT Find
which only looks for executable files in $PATH. It will not find:
| Type | Found by which? | Use instead |
|---|---|---|
| Shell builtins | ❌ No | type |
| Aliases | ❌ No | type or alias |
| Shell functions | ❌ No | type or declare -f |
| Keywords | ❌ No | type |
Example:
$ which cd
# (no output — cd is a shell builtin)
$ which ll
# (no output — ll is an alias)
$ type cd
cd is a shell builtin
$ type ll
ll is aliased to `ls -la'
type vs which
| Feature | type | which |
|---|---|---|
| Finds builtins | ✅ Yes | ❌ No |
| Finds aliases | ✅ Yes | ❌ No |
| Finds functions | ✅ Yes | ❌ No |
| Finds keywords | ✅ Yes | ❌ No |
| Finds external commands | ✅ Yes | ✅ Yes |
| Shows all matches | ✅ Yes (-a) | ✅ Yes (-a) |
| POSIX standard | ✅ Yes | ❌ No (non-standard) |
| Recommended | ✅ Yes | ⚠️ Use with caution |
Note:
whichis not part of POSIX —typeis the more portable and reliable choice. On some systems,whichmay behave differently or not exist.
Complete Example Session
# ============================================
# PART 1: EXPLORING /usr/bin
# ============================================
$ ls /usr/bin | head -20
[
2to3
2to3-3.10
7z
aa-enabled
aa-exec
ab
...
$ ls /usr/bin | wc -l
1876
# ============================================
# PART 2: TYPES OF COMMANDS
# ============================================
# Shell builtin
$ type cd
cd is a shell builtin
$ type pwd
pwd is a shell builtin
$ type echo
echo is a shell builtin
$ type exit
exit is a shell builtin
# External command
$ type mv
mv is /usr/bin/mv
$ type grep
grep is /usr/bin/grep
$ type git
git is /usr/local/bin/git
# Alias
$ type ll
ll is aliased to `ls -la'
$ type la
la is aliased to `ls -A'
# Keyword
$ type for
for is a shell keyword
$ type while
while is a shell keyword
$ type if
if is a shell keyword
# ============================================
# PART 3: TYPE WITH MULTIPLE ARGUMENTS
# ============================================
$ type cd mv ls pwd
cd is a shell builtin
mv is /usr/bin/mv
ls is aliased to `ls --color=auto'
pwd is a shell builtin
$ type -t cd mv ls pwd for
builtin
file
alias
builtin
keyword
# ============================================
# PART 4: TYPE WITH -a (ALL MATCHES)
# ============================================
$ type -a ls
ls is aliased to `ls --color=auto'
ls is /usr/bin/ls
ls is /bin/ls
$ type -a echo
echo is a shell builtin
echo is /usr/bin/echo
echo is /bin/echo
# ============================================
# PART 5: WHICH COMMAND
# ============================================
$ which ls
/usr/bin/ls
$ which mv
/usr/bin/mv
$ which git
/usr/local/bin/git
$ which ls python git
/usr/bin/ls
/usr/bin/python
/usr/local/bin/git
# ============================================
# PART 6: WHICH WITH -a
# ============================================
$ which -a python
/usr/bin/python3.10
/usr/bin/python3
/usr/bin/python
$ which -a node
/usr/bin/node
/usr/local/bin/node
# ============================================
# PART 7: NOT FOUND
# ============================================
$ which blahblah
$ echo $?
1
$ type blahblah
bash: type: blahblah: not found
# ============================================
# PART 8: BUILTINS NOT FOUND BY WHICH
# ============================================
$ which cd
# (no output)
$ which pwd
# (no output)
$ which echo
# (no output on some systems — echo is builtin)
$ type cd
cd is a shell builtin
# ============================================
# PART 9: PRACTICAL — DEBUGGING
# ============================================
# Why does "ls" show colors?
$ type ls
ls is aliased to `ls --color=auto'
# → The alias adds colors
# Which Python will run?
$ which python
/usr/bin/python3.10
# → First in PATH wins
# Is "cd" a real file?
$ type -p cd
# (empty — cd is a builtin, not a file)
Quick Reference
type Options
| Option | Description |
|---|---|
| (none) | Show command type and location |
-a | Show all matches |
-t | Show type only |
-p | Show path only |
-P | Force PATH lookup |
-f | Suppress function lookup |
which Options
| Option | Description |
|---|---|
| (none) | Show path to executable |
-a | Show all matches in PATH |
Command Types
| Type | Meaning | Example |
|---|---|---|
| Builtin | Inside the shell | cd, pwd, echo |
| Keyword | Shell language keyword | if, for, while |
| Alias | Shortcut | ll, la |
| Function | Custom shell function | mkcd() |
| External | Executable file | ls, mv, grep |
Best Practices
✅ Do This:
# Use type for complete information
type cd ls mv
# Use type -a to see all matches
type -a python
# Use type -t for scripting (just the type)
if [ "$(type -t mycmd)" = "function" ]; then
echo "It's a function"
fi
# Use which to find the default executable
which python
# Use which -a to see all installed versions
which -a node
# Check exit codes for scripts
if which git > /dev/null 2>&1; then
echo "Git is installed"
fi
❌ Don’t Do This:
# Don't use which to find builtins
which cd # ❌ Returns nothing
# Don't rely on which for shell behavior
which ls # ❌ Doesn't show aliases
# Don't use which in portable scripts
# Use "command -v" instead (POSIX):
command -v ls # ✅ Portable
# Don't assume "which" output is complete
which python # ⚠️ May not show all versions
The Portable Alternative: command -v
command -v is POSIX-compliant and works everywhere:
$ command -v ls
/usr/bin/ls
$ command -v cd
cd
$ command -v ll
alias ll='ls -la'
$ command -v for
for
Why it’s better:
- ✅ Works in POSIX shells
- ✅ Finds builtins, aliases, functions, keywords
- ✅ Recommended for scripts
Replace which with command -v:
# Instead of:
if which git > /dev/null 2>&1; then
# Use:
if command -v git > /dev/null 2>&1; then
Common Pitfalls
| Pitfall | Problem | Solution |
|---|---|---|
Using which for builtins | Returns nothing | Use type or command -v |
Missing aliases with which | Wrong assumptions | Use type -a |
| Not knowing which Python runs | Wrong version | which -a python |
Expecting which to be portable | Not POSIX | Use command -v |
| Forgetting PATH order | First match wins | Check echo $PATH |
Visual: Command Resolution
$ python
│
▼
┌──────────────────────────────────┐
│ 1. Is it an alias? │
│ → Use alias if yes │
└──────────────┬───────────────────┘
│ no
▼
┌──────────────────────────────────┐
│ 2. Is it a function? │
│ → Use function if yes │
└──────────────┬───────────────────┘
│ no
▼
┌──────────────────────────────────┐
│ 3. Is it a builtin? │
│ → Use builtin if yes │
└──────────────┬───────────────────┘
│ no
▼
┌──────────────────────────────────┐
│ 4. Search PATH directories │
│ → First match wins │
│ /usr/local/bin → /usr/bin → … │
└──────────────────────────────────┘
Real-World Examples
1. Debug “Why is my command behaving differently?”
$ ll
# Shows long format with colors
$ type ll
ll is aliased to `ls -la'
# → The alias explains the behavior
2. Check Which Python Version Is Default
$ which -a python
/usr/bin/python3.10
/usr/local/bin/python3.11
# → First one wins unless PATH changes
3. Verify a Command Exists in a Script
if command -v git > /dev/null 2>&1; then
echo "Git is available"
else
echo "Please install Git"
fi
4. Create an Alias and Verify
$ alias ll='ls -la'
$ type ll
ll is aliased to `ls -la'
$ which ll
# (no output — which doesn't find aliases)
5. Find All Installations of a Program
$ which -a node
/usr/bin/node
/usr/local/bin/node
$ type -a node
node is /usr/local/bin/node
node is /usr/bin/node
# → Same information, different format
Summary
| Command | Purpose | Best For |
|---|---|---|
type | Identify command type | Complete command info |
which | Locate executable in PATH | Finding files |
command -v | Portable alternative | Scripts, POSIX |
Key takeaways:
- Commands come in five types: builtin, keyword, alias, function, external
- Most commands are external files in
/usr/binand other PATH directories typeshows all command types — builtins, aliases, functions, keywordswhichonly finds external executables — not builtins or aliasestype -ashows all matches — useful for multiple versionswhich -ashows all executables in PATHcommand -vis the portable alternative — use it in scripts
Remember: When you type a command, the shell checks in this order: alias → function → builtin → PATH. Use type to see what’s really happening, and use which (or better, command -v) to find where a program lives. This knowledge is essential for debugging and scripting!
Stop using slow, ad-bloated tool sites! 🤮
🔎 Search “KandZ Tools” on Google to use many professional utilities for free.
KandZ.me is the ultimate minimalist hub for:
✅ Finance (Mortgage, Interest, Inflation)
✅ Tech (Base64, JSON, Dev Suite, IP)
✅ Health (BMI, BMR, TDEE)
✅ Productivity (Timer, Workspace, QR)
⚡️ Fast & Private
🔒 No data leaves your device
💎 100% Free
🔗 Use it now: https://tools.kandz.me
🔖 Bookmark it—you’ll need it later!