Канали та фільтри

Останнє оновлення 2025-07-14 | Редагувати цю сторінку

Огляд

Питання

  • Як я можу комбінувати команди, що вже існують, щоб робити нові речі?
  • Як відобразити лише частину виведених даних?

Цілі

  • Explain the advantage of linking commands with pipes and filters.
  • Combine sequences of commands to get new output
  • Redirect a command’s output to a file.
  • Explain what usually happens if a program or pipeline isn’t given any input to process.

Now that we know a few basic commands, we can finally look at the shell’s most powerful feature: the ease with which it lets us combine existing programs in new ways. We’ll start with the directory shell-lesson-data/exercise-data/alkanes that contains six files describing some simple organic molecules. The .pdb extension indicates that these files are in Protein Data Bank format, a simple text format that specifies the type and position of each atom in the molecule.

BASH

$ ls

ВИХІД

cubane.pdb    methane.pdb    pentane.pdb
ethane.pdb    octane.pdb     propane.pdb

Let’s run an example command:

BASH

$ wc cubane.pdb

ВИХІД

20 156 1158 cubane.pdb

wc is the ‘word count’ command: it counts the number of lines, words, and characters in files (returning the values in that order from left to right).

If we run the command wc *.pdb, the * in *.pdb matches zero or more characters, so the shell turns *.pdb into a list of all .pdb files in the current directory:

BASH

$ wc *.pdb

ВИХІД

  20  156  1158  cubane.pdb
  12  84   622   ethane.pdb
   9  57   422   methane.pdb
  30  246  1828  octane.pdb
  21  165  1226  pentane.pdb
  15  111  825   propane.pdb
 107  819  6081  total

Note that wc *.pdb also shows the total number of all lines in the last line of the output.

If we run wc -l instead of just wc, the output shows only the number of lines per file:

BASH

$ wc -l .pdb

ВИХІД

  20  cubane.pdb
  12  ethane.pdb
   9  methane.pdb
  30  octane.pdb
  21  pentane.pdb
  15  propane.pdb
 107  total

The -m and -w options can also be used with the wc command to show only the number of characters or the number of words, respectively.

Виноска

Why Isn’t It Doing Anything?

What happens if a command is supposed to process a file, but we don’t give it a filename? Наприклад, що буде, якщо ми наберемо:

BASH

$ wc -l

але не будемо вводити *.pdb (або щось інше) після цієї команди? Since it doesn’t have any filenames, wc assumes it is supposed to process input given at the command prompt, so it just sits there and waits for us to give it some data interactively. From the outside, though, all we see is it sitting there, and the command doesn’t appear to do anything.

Якщо ви припустилися такої помилки, ви можете вийти з цього стану, утримуючи клавішу control (Ctrl), та один раз натиснувши клавішу C: Ctrl+C. Потім відпустіть обидві клавіші.

Capturing output from commands


Which of these files contains the fewest lines? It’s an easy question to answer when there are only six files, but what if there were 6000? Our first step toward a solution is to run the command:

BASH

$ wc -l *.pdb > lengths.txt

The greater than symbol, >, tells the shell to redirect the command’s output to a file instead of printing it to the screen. This command prints no screen output, because everything that wc would have printed has gone into the file lengths.txt instead. If the file doesn’t exist prior to issuing the command, the shell will create the file. Якщо файл вже існує, він буде непомітно перезаписаний, що може призвести до втрати даних. Thus, redirect commands require caution.

Команда ls lengths.txt підтверджує, що файл існує:

BASH

$ ls lengths.txt

ВИХІД

lengths.txt

We can now send the content of lengths.txt to the screen using cat lengths.txt. The cat command gets its name from ‘concatenate’ i.e. join together, and it prints the contents of files one after another. There’s only one file in this case, so cat just shows us what it contains:

BASH

$ cat lengths.txt

ВИХІД

  20  cubane.pdb
  12  ethane.pdb
   9  methane.pdb
  30  octane.pdb
  21  pentane.pdb
  15  propane.pdb
 107  total
Виноска

Output Page by Page

We’ll continue to use cat in this lesson, for convenience and consistency, but it has the disadvantage that it always dumps the whole file onto your screen. Більш корисною на практиці є команда less (наприклад, less lengths.txt). This displays a screenful of the file, and then stops. You can go forward one screenful by pressing the spacebar, or back one by pressing b. Press q to quit.

Filtering output


Next we’ll use the sort command to sort the contents of the lengths.txt file. But first we’ll do an exercise to learn a little about the sort command:

Вправа

What Does sort -n Do?

The file shell-lesson-data/exercise-data/numbers.txt contains the following lines:

10
2
19
22
6

If we run sort on this file, the output is:

ВИХІД

10
19
2
22
6

If we run sort -n on the same file, we get this instead:

ВИХІД

2
6
10
19
22

Explain why -n has this effect.

The -n option specifies a numerical rather than an alphanumerical sort.

We will also use the -n option to specify that the sort is numerical instead of alphanumerical. This does not change the file; instead, it sends the sorted result to the screen:

BASH

$ sort -n lengths.txt

ВИХІД

  9  methane.pdb
 12  ethane.pdb
 15  propane.pdb
 20  cubane.pdb
 21  pentane.pdb
 30  octane.pdb
107  total

We can put the sorted list of lines in another temporary file called sorted-lengths.txt by putting > sorted-lengths.txt after the command, just as we used > lengths.txt to put the output of wc into lengths.txt. Once we’ve done that, we can run another command called head to get the first few lines in sorted-lengths.txt:

BASH

$ sort -n lengths.txt > sorted-lengths.txt
$ head -n 1 sorted-lengths.txt

ВИХІД

  9 methane.pdb

Using -n 1 with head tells it that we only want the first line of the file; -n 20 would get the first 20, and so on. Since sorted-lengths.txt contains the lengths of our files ordered from least to greatest, the output of head must be the file with the fewest lines.

Виноска

Redirecting to the same file

It’s a very bad idea to try redirecting the output of a command that operates on a file to the same file. For example:

BASH

$ sort -n lengths.txt > lengths.txt

Виконання таких дій може надати вам некоректні результати та/або видалити вміст файлу lengths.txt.

Вправа

What Does >> Mean?

We have seen the use of >, but there is a similar operator >> which works slightly differently. Ми дізнаємося про відмінності між цими двома операторами, надрукувавши кілька рядків. We can use the echo command to print strings e.g.

BASH

$ echo The echo command prints text

ВИХІД

The echo command prints text

Тепер протестуйте наведені нижче команди, щоб виявити різницю між цими двома операторами:

BASH

$ echo hello > testfile01.txt

and:

BASH

$ echo hello >> testfile02.txt

Підказка: Спробуйте виконати кожну команду двічі поспіль, а потім переглянути вихідні файли.

In the first example with >, the string ‘hello’ is written to testfile01.txt, but the file gets overwritten each time we run the command.

We see from the second example that the >> operator also writes ‘hello’ to a file (in this case testfile02.txt), but appends the string to the file if it already exists (i.e. when we run it for the second time).

Вправа

Appending Data

We have already met the head command, which prints lines from the start of a file. tail is similar, but prints lines from the end of a file instead.

Розглянемо файл shell-lesson-data/exercise-data/animal-counts/animals.csv. After these commands, select the answer that corresponds to the file animals-subset.csv:

BASH

$ head -n 3 animals.csv > animals-subset.csv
$ tail -n 2 animals.csv >> animals-subset.csv
  1. Перші три рядки файлу animals.csv
  2. Останні два рядки файлу animals.csv
  3. Перші три рядки та останні два рядки файлу animals.csv
  4. Другий і третій рядки файлу animals.csv

Варіант 3 є правильним. Щоб варіант 1 був правильним, потрібно виконати лише команду head. Щоб варіант 2 був правильним, нам слід виконати лише команду tail. Щоб варіант 4 був коректним, нам слід передати вивід команди head у команду tail -n 2 виконавши head -n 3 animals.csv | tail -n 2 > animals-subset.csv

Passing output to another command


In our example of finding the file with the fewest lines, we are using two intermediate files lengths.txt and sorted-lengths.txt to store output. This is a confusing way to work because even once you understand what wc, sort, and head do, those intermediate files make it hard to follow what’s going on. We can make it easier to understand by running sort and head together:

BASH

$ sort -n lengths.txt | head -n 1

ВИХІД

  9 methane.pdb

The vertical bar, |, between the two commands is called a pipe. It tells the shell that we want to use the output of the command on the left as the input to the command on the right.

This has removed the need for the sorted-lengths.txt file.

Combining multiple commands


Nothing prevents us from chaining pipes consecutively. We can for example send the output of wc directly to sort, and then send the resulting output to head. This removes the need for any intermediate files.

We’ll start by using a pipe to send the output of wc to sort:

BASH

$ wc -l *.pdb | sort -n

ВИХІД

   9 methane.pdb
  12 ethane.pdb
  15 propane.pdb
  20 cubane.pdb
  21 pentane.pdb
  30 octane.pdb
 107 total

We can then send that output through another pipe, to head, so that the full pipeline becomes:

BASH

$ wc -l *.pdb | sort -n | head -n 1

ВИХІД

   9 methane.pdb

This is exactly like a mathematician nesting functions like log(3x) and saying ‘the log of three times x’. In our case, the algorithm is ‘head of sort of line count of *.pdb’.

The redirection and pipes used in the last few commands are illustrated below:

Перенаправлення та канали різних команд: "wc -l *.pdb" перенаправить виведення до терміналу. "wc -l *.pdb > lengths" will direct output to the file"lengths". "wc -l *.pdb | sort -n | head -n 1" will build a pipeline where theoutput of the "wc" command is the input to the "sort" command, the output ofthe "sort" command is the input to the "head" command and the output of the"head" command is directed to the shell
Вправа

Piping Commands Together

У нашому поточному каталозі ми хочемо знайти 3 файли, які мають найменшу кількість рядків. Яка з наведених нижче команд підійде для цього?

  1. wc -l * > sort -n > head -n 3
  2. wc -l * | sort -n | head -n 1-3
  3. wc -l * | head -n 3 | sort -n
  4. wc -l * | sort -n | head -n 3

Варіант 4 є рішенням. Символ каналу | використовується для під’єднання виводу однієї команди до входу іншої. Символ > використовується для перенаправлення стандартного виводу до файлу. Спробуйте це у каталозі shell-lesson-data/exercise-data/proteins!

Tools designed to work together


This idea of linking programs together is why Unix has been so successful. Instead of creating enormous programs that try to do many different things, Unix programmers focus on creating lots of simple tools that each do one job well, and that work well with each other. This programming model is called ‘pipes and filters’. We’ve already seen pipes; a filter is a program like wc or sort that transforms a stream of input into a stream of output. Майже всі стандартні інструменти Unix можуть працювати таким чином. Unless told to do otherwise, they read from standard input, do something with what they’ve read, and write to standard output.

The key is that any program that reads lines of text from standard input and writes lines of text to standard output can be combined with every other program that behaves this way as well. You can and should write your programs this way so that you and other people can put those programs into pipes to multiply their power.

Вправа

Pipe Reading Comprehension

Файл з назвою animals.csv (у каталозі shell-lesson-data/exercise-data/animal-counts) містить наступні дані:

2012-11-05,deer,5
2012-11-05,rabbit,22
2012-11-05,raccoon,7
2012-11-06,rabbit,19
2012-11-06,deer,2
2012-11-06,fox,4
2012-11-07,rabbit,16
2012-11-07,bear,1

What text passes through each of the pipes and the final redirect in the pipeline below? Note, the sort -r command sorts in reverse order.

BASH

$ cat animals.csv | head -n 5 | tail -n 3 | sort -r > final.txt

Підказка: створюйте конвеєр по одній команді за раз, щоб перевіряти своє розуміння

Команда head виділяє перші 5 рядків з файлу animals.csv. Then, the last 3 lines are extracted from the previous 5 by using the tail command. За допомогою команди sort -r ці 3 рядки сортуються у зворотному порядку. І нарешті, результат перенаправляється до файлу final.txt. The content of this file can be checked by executing cat final.txt. Файл повинен містити наступні рядки:

2012-11-06,rabbit,19
2012-11-06,deer,2
2012-11-05,raccoon,7
Вправа

Pipe Construction

Для файлу animals.csv з попередньої вправи розглянемо наступну команду:

BASH

$ cut -d , -f 2 animals.csv

Команда cut використовується для видалення або ‘вирізання’ певних частин кожного рядка у файлі. Вона очікує, що рядки буде розділено на стовпчики символом Tab. A character used in this way is called a delimiter. In the example above we use the -d option to specify the comma as our delimiter character. We have also used the -f option to specify that we want to extract the second field (column). Це призведе до наступного результату:

ВИХІД

deer
rabbit
raccoon
rabbit
deer
fox
rabbit
bear

The uniq command filters out adjacent matching lines in a file. How could you extend this pipeline (using uniq and another command) to find out what animals the file contains (without any duplicates in their names)?

BASH

$ cut -d , -f 2 animals.csv | sort | uniq
Вправа

Which Pipe?

Файл animals.csv містить 8 рядків даних, відформатованих наступним чином:

ВИХІД

2012-11-05,deer,5
2012-11-05,rabbit,22
2012-11-05,raccoon,7
2012-11-06,rabbit,19
...

The uniq command has a -c option which gives a count of the number of times a line occurs in its input. Assuming your current directory is shell-lesson-data/exercise-data/animal-counts, what command would you use to produce a table that shows the total count of each type of animal in the file?

  1. sort animals.csv | uniq -c
  2. sort -t, -k2,2 animals.csv | uniq -c
  3. cut -d, -f 2 animals.csv | uniq -c
  4. cut -d, -f 2 animals.csv | sort | uniq -c
  5. cut -d, -f 2 animals.csv | sort | uniq -c | wc -l

Варіант 4. Це правильна відповідь. Якщо вам важко зрозуміти, чому, спробуйте виконати команди або фрагменти конвеєру (перед цим переконайтеся, що ви перебуваєте у каталозі shell-lesson-data/exercise-data/animal-counts).

Nelle’s Pipeline: Checking Files


Nelle has run her samples through the assay machines and created 17 files in the north-pacific-gyre directory described earlier. As a quick check, starting from the shell-lesson-data directory, Nelle types:

BASH

$ cd north-pacific-gyre
$ wc -l *.txt

The output is 18 lines that look like this:

ВИХІД

300 NENE01729A.txt
300 NENE01729B.txt
300 NENE01736A.txt
300 NENE01751A.txt
300 NENE01751B.txt
300 NENE01812A.txt
... ...

Now she types this:

BASH

$ wc -l *.txt | sort -n | head -n 5

ВИХІД

 240 NENE02018B.txt
 300 NENE01729A.txt
 300 NENE01729B.txt
 300 NENE01736A.txt
 300 NENE01751A.txt

Ого - несподіванка! Один з файлів на 60 рядків коротший за інші. Коли вона повертається до цього файлу та перевіряє його, вона бачить, що зробила цей аналіз о 8:00 ранку в понеділок — хтось, можливо, користувався машиною на вихідних, і вона забула її перезавантажити. Перед тим, як повторно проаналізувати цей зразок, вона перевіряє, чи є файли, що містять забагато даних:

BASH

$ wc -l *.txt | sort -n | tail -n 5

ВИХІД

 300 NENE02040B.txt
 300 NENE02040Z.txt
 300 NENE02043A.txt
 300 NENE02043B.txt
5040 total

Those numbers look good — but what’s that ‘Z’ doing there in the third-to-last line? All of her samples should be marked ‘A’ or ‘B’; by convention, her lab uses ‘Z’ to indicate samples with missing information. To find others like it, she does this:

BASH

$ ls *Z.txt

ВИХІД

NENE01971Z.txt    NENE02040Z.txt

Sure enough, when she checks the log on her laptop, there’s no depth recorded for either of those samples. Since it’s too late to get the information any other way, she must exclude those two files from her analysis. She could delete them using rm, but there are actually some analyses she might do later where depth doesn’t matter, so instead, she’ll have to be careful later on to select files using the wildcard expressions NENE*A.txt NENE*B.txt.

Вправа

Removing Unneeded Files

Suppose you want to delete your processed data files, and only keep your raw files and processing script to save storage. Вихідні файли закінчуються на .dat, а оброблені файли закінчуються на .txt. Which of the following would remove all the processed data files, and only the processed data files?

  1. rm ?.txt
  2. rm *.txt
  3. rm * .txt
  4. rm *.*
  1. Це призведе до вилучення файлів .txt з односимвольними назвами

  2. Це правильна відповідь

  3. The shell would expand * to match everything in the current directory, so the command would try to remove all matched files and an additional file called .txt

  4. The shell expands *.* to match all filenames containing at least one ., including the processed files (.txt) and raw files (.dat)

Ключові моменти
  • wc підраховує рядки, слова та символи у своїх вхідних даних.
  • cat виводить вміст своїх вхідних даних.
  • sort сортує вхідні дані.
  • head displays the first 10 lines of its input by default without additional arguments.
  • tail displays the last 10 lines of its input by default without additional arguments.
  • command > [file] redirects a command’s output to a file (overwriting any existing content).
  • command >> [file] додає вивід команди до файлу.
  • [first] | [second] is a pipeline: the output of the first command is used as the input to the second.
  • The best way to use the shell is to use pipes to combine simple single-purpose programs (filters).