← Back to Bash Course | Chapter 8: Input/Output & Redirection | Lesson 8 of 13

Pipes and Chaining Commands

A pipe connects the output of one command directly into the input of the next, letting you build a small assembly line of tools.

Connecting Two Commands

The pipe operator | takes the stdout of the command on its left and feeds it as stdin to the command on its right. You can chain as many commands as you like this way.

Example: Connecting Two Commands

bash
#!/bin/bash
printf "banana\napple\ncherry\n" | sort

Pipelines and Exit Status

By default, the exit status of a pipeline is the exit status of its last command, regardless of whether earlier commands failed. Enabling pipefail changes this so the pipeline fails if any stage fails.

Warning: Without pipefail, a broken first stage in a long pipeline can silently be ignored.

Example: Pipelines and Exit Status

bash
#!/bin/bash
false | true
echo "default pipeline status: $?"

set -o pipefail
false | true
echo "pipefail status: $?"
set +o pipefail

Chaining with && and ||

&& runs the next command only if the previous one succeeded (exit status 0); || runs the next command only if the previous one failed (non-zero exit status). These are used constantly for lightweight conditional logic.

Example: Chaining with && and ||

bash
#!/bin/bash
mkdir -p demo_dir && echo "directory ready"
rmdir demo_dir || echo "could not remove"

false || echo "this runs because the previous command failed"
true && echo "this runs because the previous command succeeded"

Building a Small Pipeline

Real scripts often chain several small, single-purpose tools together instead of writing one big command, which mirrors the Unix philosophy of composing simple programs.

Example: Building a Small Pipeline

bash
#!/bin/bash
printf "3\n1\n2\n1\n3\n1\n" | sort -n | uniq -c
Common Mistakes
  1. Thinking a pipeline runs commands one after another; every command in a pipeline actually starts at the same time and streams data between them.
  2. Checking $? after a pipeline and assuming it reflects the first command's exit status; by default it reflects only the last command's exit status.
  3. Forgetting that each side of a pipe runs in its own subshell, so variables set inside a piped command do not persist afterward.
Chapter Summary
  • | connects one command's stdout directly to the next command's stdin.
  • By default, $? after a pipeline reflects only the last command's exit status.
  • set -o pipefail makes the pipeline's exit status the first non-zero status among all commands.
  • Commands can be chained with && (run next only on success) and || (run next only on failure).

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.