- Конвейеры и перенаправление ввода-вывода в Linux
- Что такое конвейеры и перенаправления
- Перенаправление в файл
- Несколько наблюдений
- Сохранение в уже существующий файл
- Перенаправление из файла
- Перенаправление STDERR
- Конвейеризация
- Конаейеризация + перенаправление
- Еще несколько примеров
- Пример 1. Сортируем директорию так, чтобы папки вывелись в консоль первыми
- Пример 2. Выводим все файлы, у которых есть разрешение на запись
- Пример 3. Выводим список пользователей, у которых есть доступ к файлам в выбранном каталоге
Конвейеры и перенаправление ввода-вывода в 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 © ООО «Алгоритмы и практика»