Начнем с основ. Что делают стандартные потоки?
Программа, работающая в Unix-подобной операционной системе, может читать и записывать из/в один из 3 стандартных потоков:
- stdin (стандартный ввод) — это поток данных, который поступает в программу (например, когда программа запрашивает у вас сообщение электронной почты). Общим источником ввода является клавиатура, с которой запущена программа.
- stdout (стандартный вывод) используется программой для записи выходных данных. Обычным местом назначения вывода является текстовый терминал, который запустил программу.
- stderr (стандартная ошибка) — это место, где программа пишет свои сообщения об ошибках.
Каждому открытому файлу в Unix-подобной операционной системе назначается дескриптор файла (положительное целое число), который используется для доступа к файлу. Стандартные потоки обрабатываются как файлы, и операционная система назначает им файловые дескрипторы, которые для stdin, stdout и stderr равны 0, 1 и 2 соответственно.
Пример чтения из стандартного ввода и записи в стандартный вывод в оболочке bash:
read MY_NAME #we prompt the user for the name and read it from stdin John Doe #the user enters the name echo $MY_NAME #we write the user’s name to stdout
Назначением stderr обычно является текстовый терминал. Итак, если программа пишет сообщение об ошибке в stderr, вы увидите его в текстовом терминале:
cat ./idontexist
Вы увидите следующее сообщение об ошибке от программы cat: cat: idontexist: Нет такого файла или каталога.
перенаправление
Мы можем перенаправлять стандартные потоки. Давайте перенаправим все, что программа записывает в stderr, в файл:
cat ./idontexist 2>stderr.txt
cat
пишет сообщение об ошибке в stderr, потому что файл idontexist не существует. Часть 2>stderr.txt
перенаправляет все, что написано в stderr, в файл stderr.txt (другими словами, все, что написано в файловом дескрипторе 2, должно попасть в stderr.txt). .
Мы могли бы сделать то же самое с stdout:
echo "Hello World" 1>stdout.txt
Мы перенаправляем все, что программа echo записывает в stdout (файловый дескриптор 1), в файл stdout.txt.
Единственный оператор › (больше) перезаписывает файл, если он уже существует. Вместо этого, чтобы добавить к существующему файлу, используйте двойной оператор › (больше):
echo "Hello World" 1>>stdout.txt
Вы можете отправить содержимое файла в программу через стандартный ввод с помощью оператора ‹ (меньше), если программа это поддерживает:
echo "Hello World" 1>example.txt cat 0<example.txt
Мы отправили содержимое example.txt в файл с дескриптором 0. Таким образом, cat получит только содержимое, он не будет знать, какой файл вы читаете.
Кроме того, мы можем комбинировать перенаправления. Давайте воспользуемся программой wc
, чтобы подсчитать количество слов в одном файле и записать это число в другой файл:
echo "This file has five words" 1>words.txt wc -w 0<words.txt 1>words-count.txt cat words-count.txt
Резюме
К каждой программе, которую вы запускаете в терминале, подключено 3 стандартных потока: stdin, stdout и stderr с номерами 0, 1 и 2 файловых дескриптора соответственно. Мы можем перенаправить поток в файл или в другой поток, используя операторы › (больше чем) или ›› (двойное большее чем). Мы можем прочитать файл в стандартный поток ввода, используя оператор ‹ (меньше чем).