- Конвейеры и перенаправление ввода-вывода в Linux
- Что такое конвейеры и перенаправления
- Перенаправление в файл
- Несколько наблюдений
- Сохранение в уже существующий файл
- Перенаправление из файла
- Перенаправление STDERR
- Конвейеризация
- Конаейеризация + перенаправление
- Еще несколько примеров
- Пример 1. Сортируем директорию так, чтобы папки вывелись в консоль первыми
- Пример 2. Выводим все файлы, у которых есть разрешение на запись
- Пример 3. Выводим список пользователей, у которых есть доступ к файлам в выбранном каталоге
- Piping and Redirection
- 5 Answers 5
Конвейеры и перенаправление ввода-вывода в Linux
В предыдущих двух уроках мы познакомились с командами для фильтрации, с помощью которых мы обрабатывали данные. В этом уроке мы научимся их объединять.
Эту статью нужно читать внимательно! Даже если механизм работы всех команд для вас очевиден, для эффективного использования важно понимать все тонкости.
Что такое конвейеры и перенаправления
К каждой программе, запускаемой в командной строке, по умолчанию подключено три потока данных:
- STDIN (0) — стандартный поток ввода (данные, загружаемые в программу).
- STDOUT (1) — стандартный поток вывода (данные, которые выводит программа). По умолчанию — терминал.
- STDERR (2) — стандартный поток вывода диагностических и отладочных сообщений (например, сообщениях об ошибках). По умолчанию — терминал.
Конвейеры и перенаправления — это инструменты, которые позволяют связывать потоки между программами и файлами нужным способом.
Их работу мы продемонстрируем на нескольких примерах ниже. Общие принципы, продемонстрированные в них, будут работать с любой программой в командной строке.
Перенаправление в файл
Обычно мы выводим информацию в консоль, что довольно удобно. Но иногда нужно записать ее в файл, отправить на другой компьютер или другому человеку. Оператор > (больше) указывает командной строке на то, что мы хотим записать информацию в файл, а не выводить в консоль. Рассмотрим пример:
1. [email protected]: ls
2. barry.txt bob example.png firstfile foo1 video.mpeg
3. [email protected]: ls > myoutput
4. [email protected]: ls
5. barry.txt bob example.png firstfile foo1 myoutput video.mpeg
6. [email protected]: cat myoutput
7. barry.txt
8. bob
9. example.png
10. firstfile
11. foo1
12. myoutput
13. video.mpeg
14. [email protected]:
Давайте разберемся, что происходит:
- 1 строка. Проверяем, что находится в текущей директории.
- 3 строка. Запускаем ту же команду, но в этот раз мы используем > , чтобы указать терминалу, что мы хотим записать вывод в файл myoutput. Как вы можете заметить, мы можем не создавать файл перед записью в него — терминал сделает это автоматически.
- 4 строка. Файл действительно сам создался.
- 6 строка. Смотрим, что внатри файла.
Несколько наблюдений
Как вы могли заметить в примере выше, вывод программы сохранен в виде «один файл на одну строку». Это отличие от консоли, где всё выводится в одну строку. Дело в том, что ширина монитора известна, и программе проще адаптировать под него вывод. При перенаправлении такой роскоши у нас нет — программа может выводить данные куда угодно: например, в файл. Именно поэтому самый оптимальный вариант — «один файл на одну строку». Еще один плюс подобного подхода — упрощается управление файлами.
Совет. Имейте в виду, что при конвейеризации и перенаправлении данные не изменяются, но их форматирование может отличаться от консольного.
Обратите внимание, что файл, который мы создали для записи данных, тоже находится в нашем списке. Таков механизм работы: сначала создается файл (если он уже не существует) и только потом запускается программа, вывод которой сохраняется в файл.
Сохранение в уже существующий файл
Если мы перенаправляем данные в файл, которого не существует, он создается автоматически. Если же файл уже находится на жестком диске, то его содержимое удаляется. Только после этого в него сохраняется наш новый вывод.
1. [email protected]: cat myoutput
2. barry.txt
3. bob
4. example.png
5. firstfile
6. foo1
7. myoutput
8. video.mpeg
9. [email protected]: wc -l barry.txt > myoutput
10. [email protected]: cat myoutput
11. 7 barry.txt
12. [email protected]:
С помощью оператора >> можно получить новые данные для записи в файл.
1. [email protected]: cat myoutput
2. 7 barry.txt
3. [email protected]: ls >> myoutput
4. [email protected]: cat myoutput
5. 7 barry.txt
6. barry.txt
7. bob
8. example.png
9. firstfile
10. foo1
11. myoutput
12. video.mpeg
13. [email protected]:
Перенаправление из файла
1. [email protected]: wc -l myoutput
2. 8 myoutput
3. [email protected]: wc -l < myoutput
4. 8
5. [email protected]:
Множество программ (мы рассматривали их в предыдущих уроках) позволяют нам передавать файл в командную строку в качестве аргумента. После этого командная строка считывает и обрабатывает его содержимое.
У вас может возникнуть вопрос: «А зачем нам вообще оператор?». В примере выше прослеживается небольшое, но очень важное отличие. Обратите внимание, что после запуска wc , когда мы предоставили командной строке файл в качестве аргумента, вывод программы включает в себя имя этого файла. А вот при перенаправлении содержимого файла в wc его имя не выводится в консоль.
Это происходит из-за того, что при перенаправлении и конвейеризации все данные отправляются анонимно. То есть, как видно из примера выше, wc получает данные для обработки, но не информацию о том, откуда этот файл взялся. Соответственно, эта информация не выводится в консоль. Обычно это используется для того, чтобы не выводить ненужную информацию в консоль.
Также мы можем легко объединять две формы перенаправления, с которыми мы уже познакомились, в одну. Например, вот так:
1. [email protected]: wc -l < barry.txt >myoutput
2. [email protected]: cat myoutput
3. 7
4. [email protected]:
Перенаправление STDERR
Давайте теперь повнимательнее рассмотрим третий поток — STDERR. У каждого потока есть уникальный номер — они указаны в начале статьи на схеме. Эти номера можно использовать для идентификации потоков.
Если мы введем номер перед оператором > , то произойдет перенаправление на соответствующий поток. По умолчанию номер потока — 1. Номер потока STDERR — 2, давайте перенаправим на него.
1. [email protected]: ls -l video.mpg blah.foo
2. ls: cannot access blah.foo: No such file or directory
3. -rwxr--r-- 1 karpaff users 6 May 16 09:14 video.mpg
4. [email protected]: ls -l video.mpg blah.foo 2> errors.txt
5. -rwxr--r-- 1 karpaff users 6 May 16 09:14 video.mpg
6. [email protected]: cat errors.txt
7. ls: cannot access blah.foo: No such file or directory
8. [email protected]:
Теперь представьте, что нам нужно помимо стандартного вывода сохранить в файл еще и сообщения об ошибках? Сделать это можно перенаправив поток STDERR в STDOUT, а STDOUT — в файл. Сначала мы используем перенаправление в файл, а затем перенаправляем поток STDERR. Определить перенаправление в поток можно с помощью & перед номером потока. По умолчанию номер потока — 1.
1. [email protected]: ls -l video.mpg blah.foo > myoutput 2>&1
2. [email protected]: cat myoutput
3. ls: cannot access blah.foo: No such file or directory
4. -rwxr--r-- 1 karpaff users 6 May 16 09:14 video.mpg
5. [email protected]:
Конвейеризация
До этого мы работали только с отправкой данных из файлов и в них. Сейчас мы разберем другой механизм — отправку данных из одной программы в другую. Этот процесс называется конвейеризацией.
Для конвейеризации существует специальный оператор — | (вертикальная черта). Вот как он рабоатет: вывод из программы слева от оператора передается в качестве ввода в программу справа от оператора. В примере ниже мы выводим только первые три файла директории с помощью оператора конвейеризации.
1. [email protected]: ls
2. barry.txt bob example.png firstfile foo1 myoutput video.mpeg
3. [email protected]: ls | head -3
4. barry.txt
5. bob
6. example.png
7. [email protected]:
Конвейеризацию можно проводить с любым количеством программ. В примере ниже мы направляем вывод в tail, чтобы получить только третий файл.
1. [email protected]: ls | head -3 | tail -1
2. example.png
3. [email protected]:
Примечание. Имейте в виду, что тот вывод, который мы предоставляем в качестве вводных данных для программы, должен быть слева от нее.
Конаейеризация + перенаправление
Конвейеризацию и перенаправление можно объединить:
1. [email protected]: ls | head -3 | tail -1 > myoutput
2. [email protected]: cat myoutput
3. example.png
4. [email protected]:
Совет. Лучший способ избежать ошибок при работе с конвейеризацией — писать команды постепенно. Сначала проверьте вывод первой программы и убедитесь, что всё работает правильно. И только после этого добавляйте вторую, третью и т. д. программу. Так вы сэкономите кучу времени.
Еще несколько примеров
Рассмотрите примеры ниже, из них вы поймете, что еще можно делать с конвейерами. Эти примеры — это лишь малая часть того, как можно использовать конвейеризацию. С опытом вы сами откроете для себя множество способов их использования, которые сэкономят вам время.
Со всеми программами в примерах мы уже знакомы. Какие-то аргументы в них мы, конечно, не разбирали — детально с ними ознакомиться вы можете в соответствующих статьях. Сделать это можно и самостоятельно — методом проб и ошибок.
Пример 1. Сортируем директорию так, чтобы папки вывелись в консоль первыми
1. [email protected]: ls -l /etc | tail -n +2 | sort
2. drwxrwxr-x 3 nagios nagcmd 4096 Mar 29 08:52 nagios
3. drwxr-x--- 2 news news 4096 Jan 27 02:22 news
4. drwxr-x--- 2 root mysql 4096 Mar 6 22:39 mysql
5. .
6. [email protected]:
Пример 2. Выводим все файлы, у которых есть разрешение на запись
1. [email protected]: ls -l ~ | grep '^. w'
2. drwxrwxr-x 3 karpaff users 4096 Jan 21 04:12 dropbox
3. [email protected]:
Пример 3. Выводим список пользователей, у которых есть доступ к файлам в выбранном каталоге
Помимо этого выведем количество файлов и директорий, принадлежащих каждому пользователю.
1. [email protected]: ls -l /projects/ghosttrail | tail -n +2 | sed 's/\s\s*/ /g' | cut -d ' ' -f 3 | sort | uniq -c
2. 8 anne
3. 34 harry
4. 37 tina
5. 18 ryan
6. [email protected]:
СodeСhick.io — простой и эффективный способ изучения программирования.
2023 © ООО «Алгоритмы и практика»
Piping and Redirection
What is exact difference between piping and redirection? Where should we use piping and where should we use redirection? How they internally work?
5 Answers 5
Redirection is (mostly) for files (you redirect streams to/from files).
Piping is for processes: you pipe (redirect) streams from one process to another.
Essentially what you really do is «connect» one standard stream (usually stdout ) of one process to standard stream of another process (usually stdin ) via pipe.
Pipes have also the synchronization «side effect» : they block one process (on reading) when the other has nothing to write (yet) or when reading process cannot read fast enough (when the pipe’s buffer is full).
Piping directs the output of a program to another program.
Pipes the names of all files in the current directory to grep. Re-direction directs or appends output to a file.
ls * > file # writes all file names in current directory to the "file" ls * >> file # appends all files names in current directory to the "file"
Piping saves you the hassle of having to write to a file, then read from a file to execute a program on the output of another program.
As for how it they work internally, I am only learning that my self now. But I found this link which offers some discussion on it.
You should use piping if you want to pass outputs between programs; use redirection if you want to write to a file.
Basically redirection and piping are a few ways among many to achieve Inter Process communication in Unix.
- Redirection: Data is written to and read from a typical UNIX file. Any number of processes can interoperate. this must be used when sharing large data sets.
- Piping : Piping is a process where the output of one process is made the input of another. They were evolved in the most primitive forms of the Unix operating system. They provide unidirectional flow of communication between processes within the same system. A pipe is created by invoking the pipe system call, which creates a pair of file descriptors. [ For file descriptors read http://www.bottomupcs.com/file_descriptors.html ]
It works on simple data sharing, such as producer and consumer.
Property Comparison: Piping is always uni-directional while redirection could be used to redirecting input as well as output.
ls > grep myFileName [ Redirecting output of first command to later one ] sort < fileName.txt [ Redirecting fileName.txt file as an input to command sort ]
One can also write below to use bi-directional redirect in single statement.
While Piping , it is always output of first command supplied to the later one and that to simulanoeously.
ls | grep myName | awk ‘< print $NF >‘ [ multiple piping in a single statement ]
Note 1: command > fileName . If there is a command named fileName , that would make using redirection a lot harder and more error prone. One must check first, whether there’s a command named like destination file.
Other ways to achieve IPC in Unix system are: