DEV Community

Cover image for Terminal Mastery-Pipes, Redirection and Command Chaining
Hamed Farazi
Hamed Farazi

Posted on Edited on

Terminal Mastery-Pipes, Redirection and Command Chaining

4/10 Terminal Mastery

Pipes, Redirection and Command Chaining: Mastering Terminal Workflows

So far in this series, we've learned how to navigate the file system, create and manage files, and search through their contents.

But there's a skill that takes terminal usage to another level:

Combining commands to build powerful workflows.

Instead of running one command, reading its output, and manually passing the result to another command, we can connect commands together, redirect their output, and automate sequences of operations.

In this article, we'll explore three essential concepts:

  • Pipes (|)
  • Input and output redirection (<, >, >>)
  • Command chaining (&&, ||, ;)

We'll cover Windows PowerShell, Windows CMD, macOS, and Linux.

Let's get started.

1. Understanding Standard Input and Output

Before learning pipes and redirection, we need to understand how command-line programs communicate.

Most command-line applications use three standard streams:

Stream Number Purpose
Standard Input 0 Receives input
Standard Output 1 Displays normal output
Standard Error 2 Displays error messages

Think of them as three separate communication channels.

For example, when you run:

ls
Enter fullscreen mode Exit fullscreen mode

The command sends its normal output to Standard Output.

But if you run a command that fails, its error message usually goes to Standard Error.

This distinction becomes extremely useful when you want to save successful results without saving error messages, or the other way around.

2. What Is a Pipe?

A pipe connects the output of one command to the input of another.

The symbol is:

|
Enter fullscreen mode Exit fullscreen mode

Imagine you have a list of files and want to search that list for a specific filename.

On Linux and macOS:

ls -la | grep "report"
Enter fullscreen mode Exit fullscreen mode

Here's what happens:

  1. ls -la lists directory contents.
  2. The pipe (|) takes its output.
  3. grep "report" searches that output.
  4. Only matching lines are displayed.

Instead of manually copying the output of one command into another, the shell connects them automatically.

Pipes in Windows PowerShell

PowerShell also supports pipes:

Get-ChildItem | Where-Object { $_.Name -like "*report*" }
Enter fullscreen mode Exit fullscreen mode

This example:

  • Get-ChildItem retrieves directory items.
  • Where-Object filters them.
  • $_ represents the current object being processed.
  • .Name accesses the item's name.

Here's an important difference:

Bash and Zsh generally pass streams of text or bytes through pipes. PowerShell pipelines pass .NET objects between PowerShell commands.

That means PowerShell can filter and manipulate properties directly without first parsing text.

Pipes in Windows CMD

CMD also supports pipes:

dir | findstr "report"
Enter fullscreen mode Exit fullscreen mode

This works similarly to the Linux example:

  • dir lists directory contents.
  • findstr searches the output.
  • Matching lines are displayed.

Connecting Multiple Commands

You can connect more than two commands.

Linux and macOS:

ls -la | grep "\.log" | sort
Enter fullscreen mode Exit fullscreen mode

PowerShell:

Get-ChildItem | Where-Object Extension -eq ".log" | Sort-Object Name
Enter fullscreen mode Exit fullscreen mode

CMD:

dir /b | findstr "\.log" | sort
Enter fullscreen mode Exit fullscreen mode

This is where the terminal becomes powerful: each command performs one small task, and together they solve a larger problem.

3. Redirecting Output to a File

By default, commands usually display their output in the terminal.

But what if you want to save that output into a file?

That's where redirection comes in.

The > Operator: Overwrite a File

Linux and macOS:

ls -la > files.txt
Enter fullscreen mode Exit fullscreen mode

PowerShell:

Get-ChildItem > files.txt
Enter fullscreen mode Exit fullscreen mode

CMD:

dir > files.txt
Enter fullscreen mode Exit fullscreen mode

All three examples redirect normal output into files.txt.

Important: If the file already exists, > replaces its previous contents.

Be careful when using it with important files.

The >> Operator: Append to a File

What if you want to add new output without deleting the existing contents?

Use >>.

Linux and macOS:

echo "New log entry" >> app.log
Enter fullscreen mode Exit fullscreen mode

PowerShell:

"New log entry" >> app.log
Enter fullscreen mode Exit fullscreen mode

CMD:

echo New log entry >> app.log
Enter fullscreen mode Exit fullscreen mode

This adds the new content to the end of the file.

A useful way to remember the difference:

  • > replaces existing content.
  • >> appends new content.

4. Redirecting Error Messages

Remember the three standard streams?

We can redirect them separately.

The number 2 represents Standard Error.

For example, in Bash and Zsh:

ls /this-folder-does-not-exist 2> errors.txt
Enter fullscreen mode Exit fullscreen mode

PowerShell:

Get-ChildItem C:\ThisFolderDoesNotExist 2> errors.txt
Enter fullscreen mode Exit fullscreen mode

CMD:

dir C:\ThisFolderDoesNotExist 2> errors.txt
Enter fullscreen mode Exit fullscreen mode

Instead of displaying the error in the terminal, the error output is redirected to errors.txt.

Redirecting Both Normal Output and Errors

Sometimes you want to capture everything.

In Bash and Zsh:

some-command > output.txt 2>&1
Enter fullscreen mode Exit fullscreen mode

This means:

  1. Redirect Standard Output to output.txt.
  2. Redirect Standard Error to wherever Standard Output is currently going.

The order matters.

In PowerShell:

some-command *> output.txt
Enter fullscreen mode Exit fullscreen mode

The *> operator redirects all PowerShell streams to the specified destination.

In Windows CMD:

some-command > output.txt 2>&1
Enter fullscreen mode Exit fullscreen mode

The CMD syntax is the same as Bash for this operation.

A useful detail: In PowerShell, 2>&1 merges the error stream into the success output stream. It doesn't mean exactly the same thing as redirecting every PowerShell stream with *>.

5. Redirecting Input from a File

We've seen how to redirect command output into a file.

But can we do the opposite?

Can a command receive its input from a file?

In Bash and Zsh:

sort < names.txt
Enter fullscreen mode Exit fullscreen mode

The shell sends the contents of names.txt to the command's standard input.

In CMD:

sort < names.txt
Enter fullscreen mode Exit fullscreen mode

The same syntax works.

What About PowerShell?

PowerShell doesn't use < as a general native stdin redirection operator in the same way.

Instead, you can use the pipeline:

Get-Content names.txt | Sort-Object
Enter fullscreen mode Exit fullscreen mode

Or, for a native executable that reads standard input:

Get-Content names.txt | some-native-command
Enter fullscreen mode Exit fullscreen mode

This distinction matters when working across different shells.

6. The tee Command: Display and Save Output

Sometimes you want to see command output in the terminal and save it to a file at the same time.

On Linux and macOS, use tee:

ls -la | tee files.txt
Enter fullscreen mode Exit fullscreen mode

The output is displayed in the terminal and written to files.txt.

To append instead of replacing the file:

ls -la | tee -a files.txt
Enter fullscreen mode Exit fullscreen mode

The PowerShell Equivalent

PowerShell provides Tee-Object:

Get-ChildItem | Tee-Object -FilePath files.txt
Enter fullscreen mode Exit fullscreen mode

To append:

Get-ChildItem | Tee-Object -FilePath files.txt -Append
Enter fullscreen mode Exit fullscreen mode

What About CMD?

CMD doesn't include a built-in equivalent of tee.

You can use PowerShell for this task or install an external utility that provides similar functionality.

7. Command Chaining: Running Commands Together

So far, we've connected commands using pipes.

But sometimes we don't want to pass output between commands.

We simply want to execute multiple commands in sequence.

That's called command chaining.

There are three important operators:

Operator Meaning
; Run commands sequentially
&& Run the next command only if the previous command succeeds
`

Let's understand each one.

The {% raw %}; Operator

In Bash, Zsh, and PowerShell 7+:

mkdir project; cd project; touch README.md
Enter fullscreen mode Exit fullscreen mode

The commands execute sequentially.

The next command runs regardless of whether the previous command succeeded.

In CMD, use & instead:

mkdir project & cd project & echo Hello > README.md
Enter fullscreen mode Exit fullscreen mode

Important: ; is not the general-purpose command separator in Windows CMD.

The && Operator

This operator runs the next command only if the previous command succeeds.

Linux and macOS:

mkdir project && cd project && touch README.md
Enter fullscreen mode Exit fullscreen mode

PowerShell 7+:

New-Item -ItemType Directory project && Set-Location project
Enter fullscreen mode Exit fullscreen mode

CMD:

mkdir project && cd project && echo Hello > README.md
Enter fullscreen mode Exit fullscreen mode

If the directory creation fails, the next command won't execute.

This is useful when later commands depend on earlier ones.

The || Operator

This operator runs the next command only if the previous command fails.

Bash and Zsh:

cd missing-folder || echo "Directory not found"
Enter fullscreen mode Exit fullscreen mode

PowerShell 7+:

Set-Location missing-folder || Write-Output "Directory not found"
Enter fullscreen mode Exit fullscreen mode

CMD:

cd missing-folder || echo Directory not found
Enter fullscreen mode Exit fullscreen mode

This is especially useful for simple fallback behavior and error messages.

A Note About Older PowerShell Versions

Native && and || support was introduced in PowerShell 7.

If you're using Windows PowerShell 5.1, these operators aren't available as command-chain operators.

You can use conditional logic instead:

New-Item -ItemType Directory project

if ($?) {
    Set-Location project
}
Enter fullscreen mode Exit fullscreen mode

For native executables, $LASTEXITCODE is often the better choice when you need to check the program's exit code.

8. Understanding Exit Codes

How does a shell know whether a command succeeded?

Most command-line programs return an exit code when they finish.

Conventionally:

  • 0 means success.
  • A non-zero value means an error or another unsuccessful result.

Bash and Zsh

Check the previous command's exit code:

echo $?
Enter fullscreen mode Exit fullscreen mode

PowerShell

PowerShell has two useful variables:

$?
Enter fullscreen mode Exit fullscreen mode

This indicates whether the previous command succeeded from PowerShell's perspective.

For native executables, use:

$LASTEXITCODE
Enter fullscreen mode Exit fullscreen mode

It contains the exit code returned by the most recently executed native program.

Windows CMD

Use:

echo %ERRORLEVEL%
Enter fullscreen mode Exit fullscreen mode

These values are important when building scripts and automated workflows.

9. Real-World Examples

Let's combine everything we've learned.

Example 1: Save a Directory Listing

Linux and macOS:

ls -la > directory-report.txt
Enter fullscreen mode Exit fullscreen mode

PowerShell:

Get-ChildItem | Out-File directory-report.txt
Enter fullscreen mode Exit fullscreen mode

CMD:

dir > directory-report.txt
Enter fullscreen mode Exit fullscreen mode

Example 2: Search for Errors in a Log File

Linux and macOS:

grep -i "error" app.log > errors.txt
Enter fullscreen mode Exit fullscreen mode

PowerShell:

Select-String -Path app.log -Pattern "error" | Out-File errors.txt
Enter fullscreen mode Exit fullscreen mode

CMD:

findstr /i "error" app.log > errors.txt
Enter fullscreen mode Exit fullscreen mode

Example 3: Create a Project Structure

Bash and Zsh:

mkdir my-project && cd my-project && mkdir src docs tests
Enter fullscreen mode Exit fullscreen mode

PowerShell 7+:

New-Item -ItemType Directory my-project && Set-Location my-project && New-Item -ItemType Directory src, docs, tests
Enter fullscreen mode Exit fullscreen mode

CMD:

mkdir my-project && cd my-project && mkdir src docs tests
Enter fullscreen mode Exit fullscreen mode

Example 4: Keep a Record of Command Output

Linux and macOS:

some-command 2>&1 | tee command.log
Enter fullscreen mode Exit fullscreen mode

PowerShell:

some-command *>&1 | Tee-Object -FilePath command.log
Enter fullscreen mode Exit fullscreen mode

These examples are useful when troubleshooting applications or keeping records of command execution.

10. Common Mistakes to Avoid

1. Confusing > with >>

Using > accidentally can erase existing file contents.

2. Assuming every shell behaves the same way

PowerShell, CMD, Bash, and Zsh have different features and syntax.

3. Forgetting the order of redirection

In Bash and CMD:

command > output.txt 2>&1
Enter fullscreen mode Exit fullscreen mode

is not equivalent to:

command 2>&1 > output.txt
Enter fullscreen mode Exit fullscreen mode

Redirections are processed from left to right.

4. Using && in Windows PowerShell 5.1

Remember that native && and || support requires PowerShell 7 or later.

5. Assuming a pipe always passes plain text

PowerShell pipelines can pass structured objects, while traditional Unix pipelines generally pass byte streams.

11. Practice Exercises

Try these exercises in your preferred terminal.

Exercise 1: List the files in your current directory and save the result to files.txt.

Exercise 2: Append a new line to that file without deleting its existing content.

Exercise 3: Search a log file for the word error and save matching results into another file.

Exercise 4: Create a directory named terminal-practice, enter it, and create three subdirectories: src, docs, and tests.

Exercise 5: Run a command that intentionally fails and redirect its error output into a file.

Exercise 6: Use a pipe to filter a directory listing by filename.

Try implementing each exercise in Bash or Zsh, PowerShell, and CMD. Pay attention to the differences.

Quick Reference

Task Bash / Zsh PowerShell CMD
Pipe `\ ` `\
Overwrite output {% raw %}> > >
Append output >> >> >>
Redirect errors 2> 2> 2>
Run sequentially ; ; (7+ also) &
Run on success && && (7+) &&
Run on failure ` `
Display and save tee Tee-Object External utility / PowerShell

What's Next?

You've now learned how to combine commands, redirect their output, handle errors, and build more efficient terminal workflows.

In the next article, we'll explore something every developer eventually needs to understand:

Users, Permissions and Administrative Privileges.

We'll learn how file permissions work, how to execute commands with elevated privileges, and how Windows and Unix-like systems handle access control differently.

See you in Article 05!

Top comments (0)