Linux
Beginner 13 min read Linux

Shell Basics: Navigation, Pipes & Redirection

The shell is the interface between you and the Linux kernel — and the single most used tool in a DevOps day. Learn what a shell is, how bash compares to zsh and fish, how stdin/stdout/stderr work, and master pipes, redirection, exit codes, PATH lookup and tab completion so you can chain commands into powerful one-liners.

shellbashzshfishstdinstdoutstderrpipesredirectionexit codes$?PATHtab completionlinux
Introduction

What is this?

The shell is a program that reads the commands you type and turns them into actions performed by the kernel — running programs, moving files, starting services. It is also a tiny programming language with variables, conditionals and loops, which is why nearly every server admin writes shell one-liners and scripts every single day.

Motivation

Why do you need it?

  • The shell is the universal remote control for Linux: no matter which distro, cloud or container, the same bash commands work.
  • Composing commands with pipes and redirection lets you solve in one line what would take a GUI several clicks — and it scales to thousands of servers.
  • Understanding streams and exit codes is the foundation for debugging: every script, cron job and CI pipeline reports success or failure the same way.
  • Shell fluency lets you read others' scripts, runbooks and CI files with confidence instead of copying them blindly.
  • Almost every higher-level tool — Ansible, Kubernetes, Dockerfiles — ultimately runs shell commands, so shell knowledge never goes stale.
Think about it

Mental model

Imagine

A translator who turns your orders into precise instructions for the staff

Think of

The shell turning your commands into kernel requests

You speak in short phrases (ls, grep, systemctl restart nginx) and the shell translates them into the exact system calls the kernel needs, then reports back with results or errors. Change the translator (bash, zsh, fish) and the language stays recognisably the same.

Mechanics

How it works

  • The shell reads a line, expands variables, wildcards and aliases, then splits it into a command name and its arguments.
  • The command name is resolved by checking aliases, builtins, then every directory listed in $PATH — in order — until a matching binary or script is found.
  • Every process starts with three file descriptors: stdin (0), stdout (1) and stderr (2). Pipes and redirection simply re-wire these between processes.
  • The shell forks a child process for external commands, waits for it to finish, then records its exit status in the special variable $? (0 = success).
  • A pipe (|) connects the stdout of the left process to the stdin of the right one, letting small focused programs be chained into a single data flow.

How a command flows from your keyboard to a result, and how streams are wired.

You type
Shell
Streams
Pipeline
Exit status
Reference

Key commands

echo "Hello, Linux"

The echo builtin prints its arguments to standard output.

Hello, Linux
ls -l

List files in the current directory in long format.

total 12
-rw-r--r-- 1 dev dev  22 Aug  8 10:00 notes.txt
-rw-r--r-- 1 dev dev 120 Aug  8 10:02 todo.txt
echo $?

Print the exit status of the previous command. 0 means it succeeded.

0
echo $PATH

Show the directories the shell searches, in order, when you type a command name.

/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
type cd

Reveal that cd is a shell builtin, not an external program.

cd is a shell builtin
ps aux | grep nginx

Pipe the full process table into grep to keep only lines mentioning nginx.

root  12345  0.0  0.1 123456 7890 ?  Ss  Aug07  0:00 nginx: master process
Hands-on

Examples

One pipeline that reads, transforms and saves data

One pipeline that reads, transforms and saves data
# Count how many times each user logged in, keep the top 5, save it
grep 'session opened' /var/log/auth.log \
| awk '{print $1}' \
| sort | uniq -c | sort -rn \
| head -n 5 > top-logins.txt
# Verify the result
cat top-logins.txt

Each stage does exactly one job: grep keeps login lines, awk extracts the username, sort/uniq counts them, sort -rn ranks descending, and head keeps the top five. The final > redirects the whole result into a file instead of the screen.

Real world

In production

  • One-liners for log triage: tail -f app.log | grep -i error | awk '{print $3}' instantly isolates failing requests.
  • Cron jobs and systemd units wrap commands in redirects so stdout and stderr land in a log file you can audit.
  • CI pipelines pipe test output into reporters: npm test 2>&1 | tee results.txt keeps both the screen and a file updated.
  • Ansible, Dockerfiles and Kubernetes init containers all execute shell commands under the hood, so shell skills map directly to those tools.
Guidelines

Best practices

  • Read commands before running them: use man <cmd> and <cmd> --help to check flags first.
  • Let the shell complete for you — Tab for commands and paths, double-Tab to list ambiguous matches.
  • Redirect stderr explicitly when you intentionally discard errors, so you never mask real problems.
  • Quote arguments that contain spaces or wildcard characters to prevent accidental expansion.
  • Check $? (or better, chain with && and ||) whenever a command must succeed before the next runs.
Watch out

Common mistakes

  • Using > when you mean >>, overwriting a log or config file instead of appending to it.
  • Forgetting that 2> and > are separate streams, so errors still appear even after redirecting stdout.
  • Putting the redirection or pipe in the wrong order, e.g. cmd 2>&1 > file which merges stderr into the old stdout.
  • Typing a command name and getting "command not found" because $PATH does not include the script directory.
Root cause analysis

Common issues

Error
command not found: myapp
Root cause

The binary is not in any directory listed in $PATH, or it is a script in the current directory (which is often not on PATH).

Fix

Run ./myapp for local scripts, or add the directory with export PATH="$PATH:/opt/myapp/bin" in ~/.bashrc.

Error
Permission denied when running a script
Root cause

The file has no execute bit, or is on a filesystem mounted with noexec.

Fix

chmod +x script.sh, or run it with bash script.sh. For noexec mounts, move the file to a normal location.

Error
File was empty after I redirected output
Root cause

The command failed but you only redirected stdout, so the error went to stderr and the file was created empty.

Fix

Redirect both streams: cmd > out.log 2>&1, then inspect the log.

When things break

Debugging tips

  • echo $? immediately after a failing command tells you whether it exited cleanly (0) or with an error code.
  • Run commands with set -x in a script, or use bash -x script.sh, to see every line as it executes.
  • ls -la and cat are your first move: confirm the file exists, is readable and has the content you expect.
  • When a pipeline produces nothing, test each stage separately and then join them one at a time.
Interviews

Interview checkpoint

Practice

Hands-on lab

Navigate, pipe and redirect like a DevOps engineer
12 min · beginner
In progress
Objectives
  • Navigate the filesystem with pwd, ls and cd
  • Compose commands with pipes and filters
  • Redirect stdout and stderr to files, overwriting and appending
  • Read exit codes with $? and chain commands conditionally

Navigate, pipe and redirect like a DevOps engineer

12 min · beginner

0/6 steps
0%
sandbox · Linux sandbox
$
Try these commands
Test yourself

Quick quiz

0/6
1

Which symbol redirects standard output to a file, overwriting it?

2

What does the 2 in 2> represent?

3

After a command fails, echo $? prints a non-zero number.

4

What does the pipe symbol (|) do in ls -la | wc -l?

5

Which stream does echo "hi" >> notes.txt use by default?

6

You run find / -name "*.conf" and the screen floods with "Permission denied" errors, burying the real matches. What is the cleanest fix?

Quick reference

Cheat sheet

Navigation
pwdPrint working directory
ls -laList all files with details
cd ~Go to your home directory
cd -Go to the previous directory
clearClear the terminal screen
Streams & redirection
cmd > fileRedirect stdout, overwrite
cmd >> fileRedirect stdout, append
cmd 2> err.logRedirect stderr only
cmd > file 2>&1Redirect both streams to one file
cmd 2>/dev/nullDiscard error messages
cmd < input.txtFeed a file as stdin
Pipes & filters
a | bFeed stdout of a into stdin of b
grep patternKeep lines matching a pattern
sort | uniq -cCount unique lines
head -n 5First 5 lines
tail -fFollow a growing file (logs)
wc -lCount lines
Shell plumbing
echo $?Exit status of the last command (0 = ok)
echo $PATHDirectories searched for commands
type cmdIs it an alias, builtin or binary?
which cmdPath of the binary that runs
alias ll="ls -la"Create a shortcut
TabAutocomplete commands, files and flags
Go deeper

Official documentation