Начнем с основ. Что делают стандартные потоки?

Программа, работающая в 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 файловых дескриптора соответственно. Мы можем перенаправить поток в файл или в другой поток, используя операторы › (больше чем) или ›› (двойное большее чем). Мы можем прочитать файл в стандартный поток ввода, используя оператор ‹ (меньше чем).