У світі інтерфейсу командного рядка програми часто взаємодіють із трьома стандартними потоками даних:
stdin): звідки програма отримує вхідні дані (зазвичай із клавіатури).stdout): куди програма надсилає свої звичайні вихідні дані (зазвичай на екран термінала).stderr): куди програма надсилає повідомлення про помилки (зазвичай на екран термінала).Пригадаймо, що ми познайомилися з ними в розділі Конвеєри та списки команд.
Конвеєри можна вважати різновидом перенаправлення: стандартні вихідні дані однієї програми надсилаються безпосередньо на стандартний ввід іншої. Конвеєри ми вже розглянули. Тут ми розглянемо перенаправлення до файлів і з файлів.
Перенаправлення в оболонці - це потужний механізм, який дає змогу змінювати призначення цих потоків. Замість того щоб програма читала з клавіатури чи писала на екран, ми можемо перенаправити ввід із файлу або надіслати вихідні дані до файлу. Це дає чималу гнучкість і контроль над тим, як програми взаємодіють із даними.
Ось найпоширеніші оператори перенаправлення та те, що вони роблять:
> (перенаправлення вихідних даних)Призначення: перенаправити стандартні вихідні дані (stdout) команди до файлу.
Поведінка:
Приклад:
# Sends the output of 'ls -l' to 'file_listing.txt'
ls -l > file_listing.txt
Перенаправлення виконується до запуску команди. Це означає, що не можна перенаправляти до того самого файлу, з якого треба читати.
date > date.txt # populate the file with the current date
cat date.txt > date.txt # 'date.txt' is now empty!
У другій команді наведеного прикладу
>> (дописування вихідних даних)Призначення: дописати стандартні вихідні дані (stdout) команди в кінець файлу.
Поведінка:
Приклад:
# Adds "Another line" to the end of the file
echo "Another line" >> file_listing.txt
< (перенаправлення вводу)Призначення: перенаправити стандартний ввід (stdin) команди з файлу.
Поведінка: команда читає вхідні дані із зазначеного файлу, а не з клавіатури.
Приклад:
# 'tr' reads from 'lowercase.txt' and
# output is redirected to 'uppercase.txt'
tr 'a-z' 'A-Z' < lowercase.txt > uppercase.txt
2> (перенаправлення помилок):stderr) команди до файлу.# Error message from 'rm' is sent to 'error_log.txt'
rm non_existent_file 2> error_log.txt
Стандартні повідомлення про помилки можна дописати до файлу за допомогою 2>>.
Існують також перенаправлення, які можуть обʼєднати і stdin, і stderr.
Докладніше описано в посібнику.
/dev/null/dev/null - це спеціальний файл, який
Іноді його називають «бітовим кошиком». Він корисний, щоб заглушити вихідні дані або помилки.
some_command > /dev/null # Discards stdout
some_command 2> /dev/null # Discards stderr
# Using /dev/null as input will prevent the command
# from reading data from the keyboard
some_command < /dev/null
Можна вказати кілька перенаправлень одразу.
some_command < input.txt > output.txt 2> error.txt
Перенаправлення можна скопіювати.
# send stderr to the same destination as stdout
some_command > output.txt 2>&1
Коли ми бачимо 2>&1, читаймо це так: «перенаправити stderr туди, куди наразі вказує stdout».
Bash обробляє інструкції перенаправлення строго зліва направо, а отже, ми можемо зробити так:
# redirect stdout to 'output1.txt'
# redirect stderr to the same place
# then change stdout to 'output2.txt'
some_command > output1.txt 2>&1 > output2.txt
У контексті програмування оболонки та операційних систем на кшталт Linux/Unix файловий дескриптор (FD) - це невідʼємне ціле число, яке слугує ідентифікатором або посиланням на відкритий файл чи ресурс вводу-виводу (I/O, ввід/вивід). Уявімо це як мітку або номер-посилання, який операційна система використовує, щоб відстежувати відкриті файли та потоки даних.
Числа, які ми бачимо ліворуч від перенаправлень, - це файлові дескриптори.
Стандартним потокам вводу-виводу відведено перші 3 файлові дескриптори:
Нові файлові дескриптори можна задати або створити за допомогою команди exec та операторів перенаправлення.
# create FD 3 as a copy of stdout
exec 3>&1
# send stdout to a log file
exec > log.txt
# then redirect both stdout and file descriptor 3
echo "some debug message" >&3 # displayed in the terminal
some_command 2>&1 # stdout and stderr send to 'log.txt'
Цей прийом може здатися досить заплутаним, але він стає в пригоді, коли наш скрипт запускає якийсь інший програмний пакет, і той автоматично перехоплює стандартні вихідні дані.
Команда bats, яку використовують для запуску модульних тестів у цьому треку, працює саме так: bats перехоплює stdout і stderr тесту, але повідомлення для налагодження, надіслані до FD 3, усе одно показуються на терміналі.
Чим корисне перенаправлення?
Перенаправлення в оболонці дають змогу тонко керувати тим, як програми взаємодіють із даними, що дозволяє будувати складні робочі процеси та ефективно керувати інформацією.