The real power of the terminal comes from composition. ls, grep, and wc are each useful on their own. But chained together with a pipe, they solve problems that would take a proper little app anywhere else.
stdin, stdout, stderr
Every command has three implicit "streams":
- stdin (standard input): what it reads as input.
- stdout (standard output): what it writes normally.
- stderr (standard error): what it writes when something goes wrong.
By default, stdout and stderr both appear in the terminal. Redirections let you send them somewhere else.
Redirecting to a file
> sends stdout to a file. Warning: it overwrites the file if it already exists.
>> appends to the end of the file instead of overwriting. Essential for logs.
Redirecting errors
2>redirects stderr (errors) to a file.&>redirects both stdout and stderr together. Useful when you want to capture everything a command produces.
The pipe: chaining commands
The pipe | sends stdout from one command to stdin of the next:
ls | grep README: lists files, keeps only those containing "README".cat access.log | grep ERROR | wc -l: counts how many "ERROR" lines are in the log file.ps aux | grep node: finds running Node.js processes.
A complete practical example
Find how many .js files are in the current folder:
Extract error lines from a log file and save them:
Redirections (GNU Bash manual)