انتقل إلى المحتوى
أمين أبوزيد
منشورBEG-006-L04

الأنابيب وإعادة التوجيه

  • الدرس 4 من 8
  • 10 دقيقة قراءة
  • مبتدئ
في هذا الدرس 11 موضوعات

هذا الدرس متاح حاليًا باللغة الإنجليزية فقط، ولم تُنشر نسخته العربية بعد.

Lesson Overview

So far every command printed its answer on the screen and the answer vanished when you scrolled. This lesson shows two ideas that make the command line far more than a typing replacement for clicking.

Redirection sends a command's output into a file instead of the screen, so you can keep it. Pipes connect two commands, so the output of the first becomes the input of the second, and a big list shrinks to just the lines you care about.

In the picture of the literal assistant: until now you gave one order at a time and listened to the answer. Now you can say "write that answer on a sheet of paper" (redirection), or "give your answer to a second assistant who crosses out everything except the lines with this word" (a pipe).

You need Lessons 2 and 3 (paths, and creating and listing files). Commands appear in Bash and PowerShell. They behave alike in spirit but differ in detail, and the lesson points out where.

Learning Objectives

By the end of this lesson you will be able to:

  • Explain what "output" and "input" mean for a command.
  • Save a command's output to a file with >, and add to a file with >>.
  • Explain the danger of > replacing a file's old contents.
  • Connect two commands with |.
  • Filter lines with grep (Bash) or Select-String (PowerShell).
  • Build a short pipeline that lists files, sorts them by size, and saves the result.
  • Say how Bash pipes and PowerShell pipes differ.

Written Explanation

Output goes somewhere

Every command has a place where its normal output goes. By default, that place is the screen. In Unix terms this is standard output. Errors travel on a separate channel, standard error, which also shows on screen by default. PowerShell has the same idea with named streams: the Success stream (like standard output) and the Error stream.

Because output is a stream and not a fixed picture on a screen, it can be pointed somewhere else.

Redirection with >

The operator > sends output to a file.

text
$ echo "first line" > notes.txt
$ cat notes.txt
first line

Nothing was printed when you ran the first command: the output went into notes.txt. If the file did not exist, it was created. Both shells work this way, and the same command works in PowerShell (Get-Content notes.txt shows the file; so does cat).

The same works for any command:

text
$ ls > list.txt
PS> Get-ChildItem > list.txt

Warning: > replaces the file's old contents, without asking. The Bash manual says the file is truncated to zero size if it already exists, and Microsoft's PowerShell documentation says > overwrites the current contents without warning. A second echo "second" > notes.txt leaves only second in the file.

Appending with >>

>> adds to the end of a file and keeps what was there. If the file does not exist, it is created.

text
$ echo "first line" > notes.txt
$ echo "second line" >> notes.txt
$ cat notes.txt
first line
second line

Rule of thumb: > for "start this file fresh", >> for "keep adding", as in a log.

Redirecting errors

Error messages go to the error channel, so ls missing > out.txt still prints the error on screen and out.txt stays empty. To capture errors, put 2 in front: ls missing 2> errors.txt. This works in Bash and also in PowerShell, where 2 is the number of the Error stream. You will use it rarely at first, but it explains why an error "ignored" your redirection.

Pipes with |

The pipe | connects the output of the command on its left to the input of the command on its right.

text
$ ls | sort

Read it as: "list the folder, then give that list to sort". The pipe does not use a file in between. A pipeline can have many steps: command1 | command2 | command3, processed left to right.

Pipes work in both shells. Microsoft's pipeline documentation defines a pipeline as commands connected by |, each sending its result to the next. The standard Unix idea is the same; I did not re-read the Bash manual's pipeline section in this session.

Filtering: grep and Select-String

The most useful partner for a pipe is a filter that keeps only the lines containing a word.

text
$ ls | grep log
app.log
log-notes.txt

PowerShell's equivalent is Select-String. A small catch: to give it plain lines of text, list names only with -Name:

text
PS> Get-ChildItem -Name | Select-String log

grep and Select-String also read files directly: grep error app.log and Select-String error app.log search app.log for lines containing error. Select-String prefixes each matching line with the file name and line number when it reads from a file. grep is case-sensitive by default; grep -i ignores case. Select-String is not case-sensitive by default.

Two shells, two kinds of pipe

In Bash, a pipe carries text. Each command in the chain reads lines of text and writes lines of text. In PowerShell, a pipe carries objects: structured things with named properties such as Name and Length. This is why PowerShell can sort files by size without parsing text:

text
PS> Get-ChildItem | Sort-Object Length

Microsoft's documentation shows exactly this pattern: get items, filter, sort by a property such as Length. In Bash you use options of the command instead: ls -lS lists a detailed view sorted by size, largest first. To reverse it in PowerShell, add -Descending: Sort-Object Length -Descending.

You do not need to master objects now. The practical rule is: in PowerShell, sort and filter by property name; in Bash, filter text with grep and use the command's own options to order.

Counting with a pipe

Pipes also count. In Bash, wc -l counts lines:

text
$ ls | wc -l
7

In PowerShell, Measure-Object counts the items it receives:

text
PS> Get-ChildItem -Name | Measure-Object

and its output includes a Count line.

Combining a pipe with redirection

Pipes and > work together. The pipe goes first and redirection last, because redirection captures the final output:

text
$ ls -lS | grep txt > big-text-files.txt
PS> Get-ChildItem | Sort-Object Length -Descending > sizes.txt

A word about file encoding in PowerShell

PowerShell 7 writes redirected output as UTF-8 without a byte-order mark, according to Microsoft's documentation. Older Windows PowerShell may use a different default encoding, so a file written with > might look garbled in another tool. If that happens, Out-File -Encoding utf8 file.txt lets you choose. I did not verify the exact default of every older version.

Examples

Example 1: Save and read (simple)

text
$ echo "buy milk" > todo.txt
$ echo "call Sam" >> todo.txt
$ cat todo.txt
buy milk
call Sam

Two lines were written: > started the file fresh and >> added to it. If todo.txt had already held old notes, the first command would have wiped them.

Example 2: Find a word in a listing (practical)

Suppose a folder holds app.log, server.log, notes.txt, and report.pdf.

text
$ ls > files.txt
$ grep log files.txt
app.log
server.log

PowerShell version:

text
PS> Get-ChildItem -Name > files.txt
PS> Select-String log files.txt

The second step finds the matches in the file; PowerShell also prints the file name and line number in front of each match. You can skip the file by piping instead: ls | grep log, or Get-ChildItem -Name | Select-String log.

Example 3: A report of the three biggest files (realistic)

You want to know which files are using space.

text
$ ls -lS | head -4 > biggest.txt
$ cat biggest.txt

ls -lS lists files with the largest first, including a "total" line at the top. head -4 keeps only the first four lines, which is that total line plus the three biggest files. Then > saves them. PowerShell version:

text
PS> Get-ChildItem | Sort-Object Length -Descending | Select-Object -First 3 > biggest.txt

Here Select-Object -First 3 keeps the first three objects. Because the pipe carries objects, you do not count a "total" line. A caution: this lists subfolders too. A folder has no Length property, so the sort may place folders in an odd position. Try it in a folder of plain files first.

Backend Insight

Backend engineers live in pipes and redirects. A server writes thousands of lines to a log file. You do not read them all: you filter. grep ERROR app.log finds the lines that matter, | wc -l counts them, and > errors.txt saves them for a colleague. A running service often has its output redirected to a log file on purpose, so that it can be read later.

The same two ideas appear later when programs are chained in build and deployment scripts. The core skill is composing small tools: each does one thing, and pipes join them.

Common Mistakes

Mistake 1: Using > when you meant >>

echo "new entry" > log.txt wipes all older entries. When in doubt, use >> or look at the file first.

Mistake 2: Reading and writing the same file in one command

grep error app.log > app.log empties app.log before grep reads it. Send the result to a different file, such as errors.txt.

Mistake 3: Putting the redirect in the wrong place

ls > files.txt | grep log sends the list into the file, and the pipe then receives nothing. Pipes first, redirect last.

Mistake 4: Using Bash tools in PowerShell, or the reverse

grep and wc are not standard in Windows PowerShell. Use Select-String and Measure-Object. In Bash, Select-String does not exist.

Exercises

Try each exercise yourself before opening the solutions.

Level A: Foundation

A1. What is the difference between > and >>?

أظهر الحل A1

A1. > writes output to a file and replaces any existing contents. >> appends to the end and keeps existing contents.

A2. What does the | symbol do?

أظهر الحل A2

A2. It sends the output of the command on its left to the command on its right as input.

A3. Which command keeps only lines containing a word: Bash and PowerShell versions?

أظهر الحل A3

A3. Bash: grep word (for example ls | grep word). PowerShell: Select-String word.

Level B: Application

B1. In a practice folder, create fruit.txt containing three lines (apple, banana, cherry) using echo and redirection. Show your commands.

أظهر الحل B1

B1. echo apple > fruit.txt, then echo banana >> fruit.txt and echo cherry >> fruit.txt. The first command uses > to start the file, the others use >> to add.

B2. Using a pipe, display only the line containing an from fruit.txt (hint: cat or Get-Content first).

أظهر الحل B2

B2. cat fruit.txt | grep an prints banana. PowerShell: Get-Content fruit.txt | Select-String an.

B3. Add a fourth line date to fruit.txt without losing the first three. Which operator did you use?

أظهر الحل B3

B3. echo date >> fruit.txt. The >> operator appends.

Level C: Challenge

C1. Write one pipeline that lists the current folder, keeps only lines containing txt, and saves them to texts.txt.

أظهر الحل C1

C1. Bash: ls | grep txt > texts.txt. PowerShell: Get-ChildItem -Name | Select-String txt > texts.txt.

C2. A teammate wrote grep warning server.log > server.log. Predict what is in server.log afterwards and explain why. Write a correct version.

أظهر الحل C2

C2. The shell opens server.log for writing first, and > truncates it to empty, so grep reads an empty file and finds nothing. Afterwards server.log is empty and the original contents are lost. A correct version: grep warning server.log > warnings.txt.

Mini Challenge

In a practice folder with at least five files of different sizes, use only pipes and redirection to produce a file report.txt that contains:

  1. Your files listed from largest to smallest.
  2. Below that, only the lines of that list that contain a word you choose (use >> for the second part).

Check your work: report.txt has both parts, and you did not overwrite the first part when adding the second.

Summary & Next Lesson

Key takeaways

  • Command output goes to the screen by default, and can be redirected.
  • > writes to a file and replaces its contents. >> appends.
  • | sends one command's output into the next command.
  • grep (Bash) and Select-String (PowerShell) keep the lines that match.
  • Pipes carry text in Bash and objects in PowerShell.
  • Put the pipe before the redirect, and never read and write the same file in one command.

Next lesson

You can now chain commands and keep their output. The next lesson, "Environment variables in the shell", shows how a shell remembers named values, and how to read and set them for the current session. Module 5 introduced PATH, and now you will set your own.

Self-check

  1. What does echo "hi" >> log.txt do if log.txt has other lines?
  2. What does ls | grep txt do?
  3. Why does grep x f.txt > f.txt lose data?
  4. Which PowerShell command sorts files by size?
  5. Which comes last in a pipeline with a redirect: the pipe or the redirect?
أظهر الإجابات
  1. It adds hi as a new line at the end and keeps the other lines.
  2. It lists the folder and shows only lines that contain txt.
  3. The shell empties f.txt before grep reads it.
  4. Get-ChildItem | Sort-Object Length.
  5. The redirect comes last.

References

  • Microsoft Learn, about_Redirection. Supports: > and >> operators, the numbered streams (Success is 1, Error is 2), that > overwrites without warning, that redirection uses UTF8NoBOM in the version documented (PowerShell 7.6), and that > is equivalent to piping to Out-File.
  • Microsoft Learn, about_Pipelines. Supports: the definition of a pipeline, that PowerShell passes objects one at a time, the Sort-Object -Property Length and Measure-Object patterns, and that native command output can be piped into cmdlets such as Select-String.
  • man7.org, bash(1) manual page. Supports: > creates a file or truncates it to zero size, and >> appends and keeps existing content.
  • Not verified on an official page: the behavior of grep, wc -l, head, ls -lS, Select-String's case sensitivity and output format, and Bash's | definition (I did not read that section). Older Windows PowerShell's default encoding was not checked either.

التطبيق

طبّق هذا الدرس بمختبر الوحدة وتمارينها واختبارها.

المختبر والتمارين الاختبار

تعليم الدرس كمكتمل اختياري ويمكنك التراجع عنه في أي وقت. يبقى تقدمك محفوظًا في هذا المتصفح.

اكتب للبحث في المستويات والمراحل والوحدات والدروس.