Стандартные потоки и перенаправление ввода/вывода в Linux
Перенаправление ввода-вывода
В системе по-умолчанию всегда открыты три "файла" -- stdin (клавиатура), stdout (экран) и stderr (вывод сообщений об ошибках на экран). Эти, и любые другие открытые файлы, могут быть перенаправлены. В данном случае, термин "перенаправление" означает получить вывод из файла, команды, программы, сценария или даже отдельного блока в сценарии и передать его на вход в другой файл, команду, программу или сценарий
При открытии дополнительных файлов, дескрипторы с 3 по 9 остаются незанятыми
Иногда дополнительные дескрипторы могут сослужить неплохую службу, временно сохраняя в себе ссылку на stdin, stdout или stderr. Это упрощает возврат дескрипторов в нормальное состояние после сложных манипуляций с перенаправлением
Оператор & представляет комбинацию канала 1 и канала 2
Промежуточные команды, которые получают входные данные через каналы, затем изменяют их и выдают выходные данные, называются фильтрами.
#Redirecting Standard Error
find /usr games 2> text-error
sort /etc 2>> text-error
sort /etc 2> /dev/null
#Redirecting Standard Input
cat < text.txt # == cat text.txt
tr -d "l" < text
#перенаправление стандартного вывода и вывода стандартной ошибки в один и тот же файл
find /usr admin &> newfile
#Command Line Pipes
#При использовании каналов выходные данные первой команды автоматически становятся входными данными второй команды
cat /etc/passwd | less
ls -l | head | wc -w
#Перенаправление нескольких потоков в один файл
#stderr перенаправлен в файл
ls -la ./ /test >> command.log 2>&1
Пустая команда :
Пустая команда это эквивалент операции NOP, может рассматриваться как синоним команды true
#Использование в качестве true
if :; then :; else echo "test"; fi
#Может использоваться как символ заполнитель там, где необхоходимо использовать два операнда
: ${username=`whoami`}
#Усечение файла до нуля, выполнение аналогично cat /dev/null > data.txt
# Символ : выступает здесь в роли местозаполнителя
: > data.txt
#Может использоваться как разделитель полей, например в переменно $PATH
echo $PATH
Примеры использования перенаправления потоков
#Перенаправление вывода в файл
ls -la 1>filename
#Перенаправление вывода в файл ( режим добавления )
ls -la 1>>filename
#Перенаправление stderr в файл
ls l 2>filename
#Перенаправление stderr в файл, режим добавления
ls l 2>>filename
#Перенаправление stdout и stderr в файл
ls l &>filename
#Перенаправление stderr на stdout
ls -la /test ./ 2>&1
# Перенаправляется файл с дескриптором i в j.
i>&j
# Перенаправляется файл с дескриптором 1 (stdout) в файл с деск-риптором j
#>&j
#Ввод из файла
#0< testC.txt
#< testC.txt
grep "url" < testC.txt
grep "url" 0< testC.txt
# Файл "filename" открывается на чтение и запись, и связывается с дескриптором "j"
# Если "filename" отсутствует, то он создается
# Если дескриптор "j" не указан, то, по-умолчанию, бередся дескриптор 0, stdin
#[j]<>filename
echo 1234567890 > File
# Записать строку в файл "File".
exec 3<> File
# Открыть "File" и связать
# с дескриптором 3.
read -n 4 <&3
# Прочитать 4 символа.
echo -n . >&3
# Записать символ точки.
exec 3>&-
# Закрыть дескриптор 3.
cat File
# ==> 1234.67890
# Произвольный доступ, да и только!
#Закрыть дескриптор входного файла n
n<&-
#Закрыть дескриптор выходного файла n
1>&-, >&-
#Допускается перенаправление нескольких потоков в один файл.
ls -yz >> command.log 2>&1
#Вывод из файла
grep ls <command.log
#Закрыть stdin
0<&-, <&-
#Закрыть stdout
1>&-, >&-
Дочерние процессы наследуют дескрипторы открытых файлов, по этой причине и работают конвееры. Чтобы предотвратить наследование дескрипторов закройте их перед запуском дочернего процесса
#перенаправляет ввод со stdin на файл
#весь ввод, вместо stdin (обычно это клавиатура), будет производиться из этого файла.
#Это дает возможность читать содержимое файла, строку за строкой, и анализировать каждую введенную строку с помощью sed и/или awk
exec <filename
# Перенаправление stdin с помощью 'exec'
# Связать дескр. #6 со стандартным вводом (stdin)
exec 6<&0
# stdin заменяется файлом "data-file"
exec < data-file
# Читается первая строка из "data-file"
read a1
# Читается вторая строка из "data-file."
read a2
echo "Следующие строки были прочитаны из файла."
echo $a1
echo $a2
# Восстанавливается stdin из дескр. #6, где он был предварительно сохранен
#+ и дескр. #6 закрывается ( 6<&- ) освобождая его для других процессов
# <&6 6<&- дает тот же результат
exec 0<&6 6<&-
#Результат
#Следующие строки были прочитаны из файла.
#"Hello"
#"World"
Аналогично, конструкция exec >filename перенаправляет вывод на stdout в заданный файл. После этого, весь вывод от команд, который обычно направляется на stdout, теперь выводится в этот файл
# Связать дескр. #6 со stdout
exec 6>&1
# stdout замещается файлом "logfile.txt"
exec > logfile.txt
# Весь вывод от команд, в данном блоке, записывается в файл
echo -n "Logfile: "
date
echo "-------------------------------------"
echo
echo "Вывод команды \"ls -al\""
echo
ls -al
echo; echo
echo "Вывод команды \"df\""
echo
df
# ----------------------------------------------------------- #
# Восстановить stdout и закрыть дескр. #6.
exec 1>&6 6>&-
Использование pipe, перенаправлений и фильтров
Конвееры ( pipe ) - способ с помощью которого stdout одного процесса перенаправляется на
stdin другого
Конвейер исполняется в дочернем процессе, поэтому не имеет доступа к переменным сценария.
#Подсчет файлов с названием test в каталоге и в его подкаталогах
find /usr/share -name test | wc -l
#Замените все повторяющиеся пробелы в отсортированном по алфавиту файле contents.txt одним пробелом.
sort contents.txt | tr -s " "
# > - Принудительное перенаправление, даже если установлен ключ noclobber option
set -C test2
echo "test" > test2
-bash: test2: не удаётся перезаписать существующий файл
echo "test" >| test2
Символы < и >
Могут применяться как операторы сравнения в if
Могут применяться как операторы перенаправления вывода
Или как границы отдельных слов в регулярных выражениях
#Сравнение
if [[ 1 > 2 ]] ; then echo "Верно"; else echo "Ложь"; fi
#Поиск отдельного слова
grep -rni '\' bash_scripts
Источники
Связанные темы
Использование команды tee в Linux
Использование wget и curl в Linux
Команда chattr и lsattr в Linux
Использование awk Linux Alpine
Блокировка пользователя в Linux
Проверка на необходимость перезапуска после обновления пакетов
Архивирование и сжатие файлов в Linux
Полезные команды и скрипты Linux
Условная конструкция if в Linux
Использование оператора select в языке shell
Внутренние и внешние команды linux
Использование конструкции case в Linux