Три направления ввода-вывода являются выделенными - стандартный ввод, вывод и поток ошибок (stdin, stdout, stderr ). По умолчанию, все три потока связаны (ассоциированы) с терминалом. При этом программа выводит все свои сообщения в том числе и об ошибках на терминал. Shell позволяет перенаправить эти стандартные потоки, установить ввод-вывод и объединение потоков.

Перенаправление потоков ввода-вывода.

>file Перенаправление стандартного потока вывода в файл file

>>file -Перенаправление стандартного потока вывода в файл file с добавлением в конец файла.

-получение стандартного потока ввода из файла file.

prog1 | prog2 -Передача выходного потока программы prog1 во входной поток программы prog2.

n>file file.

n>>file -Перенаправление стандартного потока с дескриптором n в файл file с добавлением в конец файла.

n>&m -Объединение потоков с дескрипторами n и m .

$ prog1 >/dev/null 2>&1

/dev/null - это псевдоустройство, которое уничтожает направленный в него поток.

Передача потока вывода одной программы в поток ввода другой используется часто. Например:

$ gzip -d archive.tar.gz | tar –xf

Здесь происходит разархивация файла archive.tar.gz , запакованного двумя архиваторами. Выходной поток от утилиты gzip передается во входной поток утилите tar . Аналогично эту же операцию можно было выполнить и по другому:

$ gzip -d archive.tar.gz

$ tar -xf archive.tar

Поскольку язык Bourne Shell является процедурным языком программирования, в нем также как и в других подобных языках есть операторы, позволяющие управлять последовательностью выполнения команд. Необходимым оператором является проверка некоторого условия, в зависимости от выполнения которого определяется дальнейший ход программы. Таким оператором является команда test. Эта команда проверяет выполнение некоторого условия. У команды test существует два варианта вызова:

test условие

[ условие ]

Следует отметить, что между скобкой и условием необходимо наличие пробелов, иначе Shell не сможет опознать "[" как команду test . При успешном завершении test возвращает "0" .

Условия проверки файлов:

-f file Файл "file" является обычным файлом.

-d file Файл "file" является каталогом.
-c file Файл "file" является специальным файлом.
-r file Файл "file" имеет разрешение на чтение.

-w file Файл "file" имеет разрешение на запись.

-x file Файл "file" имеет разрешение на исполнение.

-s file Файл "file" не пустой.

Условия проверки строк:

string1=string2 Строки string1 и string2 совпадают.

string1!=string2 Строки string1 и string2 не совпадают.

-n string1 Строка string1 существует.

-z string1 Строка string1 не существует.

Условия операций с целыми числами:

x -eq y x равно y

x -ne y x не равно y

x -gt y x больше y

x -ge y x больше или равно y

x -lt y x меньше y

x -le y x меньше или равно y

В этом случае команда test воспринимает строки именно как целые числа. Нулевому значению так же соответствует пустая строка.

Логические операции в контексте test

! (not) Логическое "НЕ"

-o (or) Логическое "ИЛИ"

-a (and) Логическое "И"

Условный оператор "if "

Общий вид использования условного оператора if представляется следующим образом:

if <условие>

then <список команд>

[ elif <условие>

then <список> ]

Выражения, выделенные в квадратных скобках, являются необязательными. Т.е. можно представить наиболее употребительную "порезанную" модификацию условного оператора:

if <условие>

then <список команд>

В этом случае если <условие> выполнено (код завершения 0) то выполняется <список команд>. В противном случае <список команд> пропускается.

Оператор выбора case

В общем случае синтаксис оператора case выглядит следующим образом:

case <строка> in

Шаблон 1)

........

Шаблон2)

........

........

Значение <строка> сравнивается с шаблонами, по порядку. Если было найдено совпадение, тогда выполняются команды соответствующего раздела. Следует отметить, что шаблоны допускают использование масок. Если совпадения не было найдено, тогда выполняются команды из раздела с шаблоном "*" (аналогично default селектора switch в С ).

Для примера приведем кусочек инициализационного скрипта BSD UNIX . Здесь переменные (inetd_enable и inetd_flags ) были получены из другого файла (rc.conf).

. /etc/rc.conf

case {$inetd_enable} in

)

if [ -x /usr/sbin/inetd ]; then

/usr/sbin/inetd $inetd_flags

fi

;;

esac

Оператор цикла с перечислением for

Синтаксис оператора for

for <имя>

<список команд>

Фрагмент, выделенный в квадратные скобки, может отсутствовать. Оператор for обеспечивает выполнение цикла столько раз, сколько слов в списке значений. При этом переменная <имя> принимает последовательно значения слов из списка. Сам по себе список может формироваться из вывода других команд. Если же список отсутствует, тогда <имя> принимает значения, переданные как позиционные параметры скрипта.

Оператор цикла с истинным условием while

Синтаксис оператора while в общем случае имеет следующую структуру:

while <условие>

<список команд>

Оператор while предпочтителен тогда, когда не известен заранее список значений параметров. Список команд будет выполняться в цикле до тех пор, пока сохраняется истинность условия. При первом входе в цикл условие должно выполняться.

Оператор цикла с ложным условием until

Синтаксис оператора until в общем случае имеет следующую структуру:

until <условие>

<список команд>

Список команд будет выполняться в цикле до тех пор, пока сохраняется ложность условия. При первом входе в цикл условие не должно выполняться. Следует заметить, что условие цикла проверяется на ложность после каждого, в т.ч. и первой выполненной команды в цикле.

Основные команды ОС UNIX для работы с файлами

1. Команда pwd .

Синтаксис: pwd .

Описание: команда выводит имя текущей директории для работающего командного интерпретатора.

Задание 1.

Воспользуйтесь командой pwd для определения своей домашней директории.

Отразите команду и результат ее работы в отчете.

2. Команда man .

Синтаксис: man имя.

Имя - это имя интересующей нас команды, утилиты, системного вызова, библиотечной функции, файла.

Описание: UNIX MANUAL - руководство по операционной системе UNIX. Информация оттуда доступна в интерактивном режиме с помощью утилиты man .

Задание 2.

С помощью утилиты man посмотрите информацию о команде pwd.

Запишите кратко информацию о команде в отчет (на русском языке).

3. Команда cd .

Синтаксис:cd имя_директории.

Описание: это команда смены текущей директории. Имя_директории - это полное или относительное имя директории, которую вы хотите сделать текущей.

cd без параметров текущей сделает вашу домашнюю директорию.

Задание 3.

Сделайте текущей директорию на уровень выше. Проверьте это, затем вернитесь в свою домашнюю директорию. Проверьте смену директории.

Выполнение проделанных команд отразите в отчете.

4. Команда ls .

Синтаксис: ls имя_директории

Описание: команда просмотра состава указанной директории.

ls без параметров распечатывает список файлов из текущей директории.

В полученный список не войдут файлы, имена которых начинаются с символа “. ” - файлы, созданные различными системными программами в своих целях. Посмотреть полный список файлов можно, указав в команде ls ключ “-a”,

т.е. ls -aимя_директории

Права доступа к файлам

С каждым файлом в ОС UNIX связано 12-битное слово, называемое «правами доступа» к файлу.

Младшие 9 бит этого слова объединены в три группы по три бита; каждая группа задает права доступа для владельца файла, для его группы и для всех остальных пользователей. Три бита в каждой группе отвечают за право на чтение, запрос и использование файла.

Чтобы узнать права доступа к тому или иному файлу, можно воспользоваться командой

, например:

> ls -l /bin/cat

Расположенная в начале строки группа символов -rwxr-xr-x показывает тип файла (первый символ; минус означает, что мы имеем дело с обыкновенным файлом, буква d означала бы каталог и т.п.) и права доступа, соответственно, для владельца (в данном случае rwx , т.е. чтение, запись и исполнение), группы и всех остальных (в данном случае r-x , т.е. права на запись отсутствуют). Таким образом, файл /bin/cat доступен любому пользователю на чтение и исполнение, но модифицировать его может только пользователь root (т.е. администратор).

Можно записать слово прав доступа к файлу в виде восьмеричного числа (3 знака - восьмеричная цифра), трехзначного (владелец, группа, остальные пользователи) каждый знак в этом трехзначном восьмеричном числе формируется как сумма прав: 4- права на чтение, 2- права на запись, 1 - на использование (из двоичной триады): (111) 2 =2 0 +2 1 +2 2 =(1+2+4) 10 .

Например, 7 = 1 + 2 + 4 Þ права rwx

4 2 1

6 = 0 + 2+ 4 Þ права rw- -

4 2 0

В трехзначном числе задания прав: 744 для владельца определены все права, для группы - только чтение, для остальных пользователей - только на чтение.

Для использования прав доступа к файлам используется команда chmod , которая позволяет задать новые права доступа в виде восьмеричного числа, например:

$ chmod 744 filel.c.

Задание 4.

а) Для получения полной информации о команде ls воспользуйтесь утилитой man. Перенаправьте вывод команды в какой-либо текстовый файл.

б) Посмотрите полное содержимое текущей директории и перенаправьте этот вывод также в текстовый файл.

в) С помощью команды ls -l <имя_файла> выведите информацию о правах доступа к тому текстовому файлу, с которым вы работали в п. 4б, затем перенаправьте эту информацию в тот же текстовый файл. Объясните полученный вывод.

5. Команда cat .

Перенаправление ввода/вывода.

Для просмотра содержимого небольшого текстового файла на экране можно воспользоваться командой:

сat имя_файла

Внимание! Не пытайтесь просматривать таким образом содержимое директории и бинарных файлов.

Большой тестовый файл удобно просматривать командой more (описание использования найдите в UNIX MANUAL ). Почему здесь неудобна команда сat ?

В команде сat можно задавать несколько имен файлов:

сat файл1 файл 2 … файл N

при этом содержимое всех файлов подряд будет выведено на экран.

Можно перенаправить вывод в какой-нибудь файл:

сat файл 1 файл 2 > файл_ результатов

Перенаправление вывода со стандартного потока вывода (экрана) в файл является стандартным для всех команд. Перенаправить стандартный ввод (с клавиатуры), например, брать данные для программы из файла, можно с помощью знака “<”.

сat > новый_файл - создаст новый текстовый файл с содержимым, вводимым вами с клавиатуры.

Прервать процесс ввода данных-

Задание 5.

Создайте с помощью сat новый текстовый файл и просмотрите его содержимое. Перенаправьте вывод со стандартного потока в другой файл, имя которого введите с клавиатуры, и убедитесь в правильности проделанной операции.

6. Простейшие команды работы с файлами: cp, rm, mkdir, mv

Для создания новой директории используется команда:

mkdir имя_директории

Для копирования содержимого одного файла в другой используется команда:

cp файл_источник файл_назначение.

Команда

cp файл 1 файл 2 …. файл N директория назначения

служит для копирования файла или файлов в уже существующую директорию с именем директории_назначения под своими именами. Вместо имен копируемых файлов можно использовать их шаблоны. Шаблоны задаются с помощью метасимволов:

* - соответствует всем цепочкам литер, включая пустую.

Все одиночные литеры

[ …] - соответствует любой литере, заключенной в скобки. Пара литер, разделенных минусом, задает диапазон литер.

Команда

cp - r дир_источник дир_назначение

служит для рекурсивного копировария одной директории (дир_источник) в новую директориию (дир_назначение).

Вместо имен в командах копирования могут использоваться их шаблоны.

Команда

rm файл 1 файл 2 …. файл N

позволяет удалить 1 или несколько регулярных файлов из текущей директории.

Вместо имен могут использоваться шаблоны. Если хотите удалить одну или несколько директорий вместе с их содержимым (рекурсивное удаление) в команде rm используйте ключ -r

Rm-r дир 1 дир 2

Команда переименования:

mv имя_источника имя_назначения

Файл с именем имя_источника переименовывает в файл с именем имя_назначения. При этом перед выполнением команды файла с именем имя_назначения существовать не должно.

Задание 6.

Создайте новую директорию внутри своей домашней. Организуйте там небольшой тестовый файл с содержимым из двух строк:

«Изучаю работу в ОС UNIX

Организую скрипт».

Скопируйте содержимое этого файла в другой - с тем же именем, но в директории /home. Удалите первоначально созданный файл из вашей директории, если копирование прошло успешно. Проверьте содержимое использованных директориий и файлов.

Задание 7.

1). Когда вы освоили работу в интерактивном режиме с простейшими командами ОС UNIX, создайте с помощью редактора Kwriter скрипт со сценарием, соответствующим последовательному выполнению:

Задание 3,

Задание 4Б,4В,

Задание 5,

Задание 6.

В задании 6 не забудьте проверить программно успешно ли прошло копирование файла, с выдачей на экран дисплея текстовых сообщений и содержимого соответствующих директорий.

Необходимо, чтобы в командном файле была организована грамотная выдача запросов на ввод данных с клавиатуры с помощью команды: $ echo - n “текст запроса”.

2). Сохраните скрипт с именем Myscript1, запустите его на выполнение командой

sh Myscript1

введите запрашиваемые данные и проверьте полученные результаты.

3). Составьте отчет о выполненной лабораторной работе, в котором должна быть отражена и ваша работа в интерактивном режиме и со скриптом, включая текст скрипта (с комментариями) и полученные результаты на экране и в файлах.

Системные вызовы getuid и getpid

Узнать идентификатор пользователя, запустившего программу на выполнение,-UID и идентификатор группы, к которой он относится,-GID можно с помощью системных вызовов getuid() и getpid() ,применив их внутри этой программы.

Прототипы системных вызовов:

#include

#include

uid_t getuid(void);

gid_t getgid(void);

Задание 8.

Напишите, откомпилируйте и запустите программу, которая печатала бы идентификатор пользователя, запустившего программу, и идентификатор его группы.

Включите программу с результатами в отчет.

Контрольные вопросы

1. Понятие файла в ОС UNIX . Что такое домашняя директория?

2. Какие существуют средства группирования команд Shell -интерпретатора? приведите примеры использования.

3. Как осуществляется перенаправление ввода-вывода?

4. Что такое конвейер команд? приведите пример.

5. Как средствами Shell выполнить арифметические действия над Shell -переменной?

6. Каковы правила генерации имен файлов?

7. Как выполняется подстановка результатов выполнения команд?

8. Как интерпретировать строку cmd1 & cmd2 & ?

9. Как интерпретировать строку cmd1 && cmd2 & ?

10. Как интерпретировать строку cmd1 || cmd2 & ?

11. Как в UNIX определены права доступа к файлу? Какой командой их можно посмотреть для конкретного файла?

12. Как определить идентификатор пользователя, запустившего программу и идентификатор его группы?

Лабораторная работа № 3.

Процессы в операционной системе UNIX.

Цель работы

Научиться создавать процессы и освоить изменение пользовательского контекста процессов с помощью системных вызовов, применяемых в программах на языке С , в ОС UNIX .

1. Изучить организацию процессов в UNIX : понятие процесса, контекст процесса, жизненный цикл процесса, идентификация процессов, иерархическая структура процессов. Написать на С и отладить программу в соответствии с заданием 1.

2. Ознакомиться с созданием процесса в UNIX , с организацией завершения процесса. Написать и отладить программу (язык С ) в соответствии с Заданием 2, включить ее в отчет.

3. Изучить параметры функции main() в языке С , переменные среды и аргументы командной строки. Написать программу на языке С в соответствии с Заданием 3, отладить и включить ее в отчет вместе с результатами.

4. Изучить семейство функций для организации системного вызова exec().

5. Написать программу на языке С в соответствии с вариантом Задания 4, выданного преподавателем, отладить программу и продемонстрировать полученные результаты преподавателю. Включить программу с результатами в отчет.

6. Защитить работу преподавателю, ответив на контрольные вопросы.

Если вывод в (графическую) консоль не очень объёмный, можно просто выдельть мышкой кусок и вставить его в сообщение щелчком средней кнопки. В противном случае можно использовать перенаправление вывода в файл через "воронку", например так:

Some_command parameters > logfile.txt

Чтобы видеть результат выполнения на экране, и одновременно писать в файл, можно воспользоваться командой tee :

Some_command parameters | tee -a logfile.txt

Команда setterm -dump создает "слепок" буфера текущей виртуальной консоли в виде простого текстового файла с именем по умолчанию - screen.dump. В качестве ее аргумента можно использовать номер консоли, для которой требуется сделать дамп. А добавление опции -file имя_файла перенаправит этот дамп в файл с указанным именем. Опция же -append присоединит новый дамп к уже существующему файлу - "умолчальному" screen.dump или поименованному опцией -file .

Т.е. после использования команды, например

Setterm -dump -file /root/screenlog

соответственно в файле /root/screenlog будет содержимое одной страницы консоли.

Нашёл еще одно решение для копирования/вставки текста в текстовой консоли без мыши. Также можно копировать текст из буфера прокрутки (т.е. всё что на экране и выше за экраном). Чтобы лучше разобраться, читайте о консольном менеджере окон screen . Также может пригодиться увеличить размер буфера прокрутки.

1) Запускаем screen

2) Нажимаем Enter. Всё. Мы находимся в нулевом окне консоли.

3) Выполняем нужные команды, вывод которых необходимо скопировать.

4) Ctrl+A, Ctrl+[ - мы в режиме копирования. Ставим курсор на начало выделения, жмём пробел, потом ставим курсор на конец выделения, жмём пробел. Текст скопирован в буфер.

5) Ctrl+A, с - мы создали новое 1-е окно.

6) Ctrl+A, 1 - мы перешли на 1-е окно.

7) Открываем любой (?) текстовый редактор (я пробовал в mc), и жмём Ctrl+A, Ctrl+] - текст вставлен. Сохраняем.

8) Ctrl+A, Ctrl+0 - вернуться обратно в нулевое окно.

Как увеличить буфер обратной прокрутки?

Первым решением будет увеличить дефолтный (умолчальный) размер буфера в исходниках ядра и перекомпилировать его. Позвольте предположить, что вы столь же не склонны заниматься этим, как и я, и поискать средство более гибкое.

И такое средство есть, а называется оно framebuffer console , для краткости fbcon . Это устройство имеет файл документации fbcon.txt ; если вы устанавливали документацию к ядру, то он у вас есть. Выискивайте его где-то в районе /usr/share ветви (я не могу указать точный путь из-за разницы в дистрибутивах).

На этом месте прошу прощения: мы должны сделать небольшое отступление и немного поговорить о видеобуфере (framebuffer ).

Видеобуфер - это буфер между дисплеем и видеоадаптером. Его прелесть в том, что им можно манипулировать: он позволяет трюки, которые не прошли бы, будь адаптер связан напрямую с дисплеем.

Один из таких трюков связан с буфером прокрутки; оказывается, вы можете "попросить" видеобуфер выделить больше памяти буферу прокрутки. Достигается это через загрузочные параметры ядра. Сначала вы требуете framebuffer (видеобуфер); Затем запрашиваете больший буфер прокрутки.

Нижеследующий пример касается GRUB , но может быть легко адаптирован к LILO . В файле настройки GRUB - menu.lst - найдите соответствующую ядру строчку, и затем: Удалите опцию vga=xxx , если таковая присутствует. Добавьте опцию video=vesabf или то, что соответствует вашему "железу". Добавьте опцию fbcon=scrollback:128 . После этой процедуры, строка параметров ядра должна выглядеть приблизительно так:

Kernel /vmlinuz root=/dev/sdb5 video=radeonfb fbcon=scrollback:128

Спрашивается, зачем удалять опцию vga=xxx ? Из-за возможных конфликтов с видео-опцией. На своем ATI адаптере, я не могу изменить буфер прокрутки, если vga=xxx присутствует в списке. Возможно в вашем случае это не так. Если вышеперечисленные опции работают - хорошо; но что, если вы хотите увеличить число строк, или установить более мелкий шрифт на экране? Вы всегда делали это при помощи опции vga=xxx - а она-то и исчезла. Не переживайте - то же самое может быть достигнуто изменением параметров fbcon, как описано в файле fbcon.txt (но не описано в данной статье).

С опцией fbcon=scrollback:128 у меня буфер прокрутки увеличился до 17 экранов (35 раз Shift+PgUp по полэкрана). Кстати, 128 - это килобайт. Автор статьи утверждает, что больше установить нельзя. Я и не пробовал.

Можно заюзать script .

Script filename.log

когда все нужные команды выполнены -

Все записано в filename.log

В FreeBSD есть замечательная утилита watch, которая позволяет мониторить терминалы, но как оказалось, в Linux она выполняет совсем иные функции =\ Стоит погуглить на эту тему, чего-нть да найдется...

Встроенные возможности перенаправления в Linux предоставляют вам широкий набор инструментов, используемых упрощения для всех видов задач. Умение управлять различными потоками ввода-вывода в значительно увеличит производительность, как при разработке сложного программного обеспечения, так и при управлении файлами с помощью командной строки.

Потоки ввода-вывода

Ввод и вывод в окружении Linux распределяется между тремя потоками:

  • Стандартный ввод (standard input, stdin, поток номер 0)
  • Стандартный вывод (standard output, stdout, номер 1)
  • Стандартная ошибка, или поток диагностики (standard error, stderr, номер 2)

При взаимодействии пользователя с терминалом стандартный ввод передается через клавиатуру пользователя. Стандартный вывод и стандартная ошибка отображаются на терминале пользователя в виде текста. Все эти три потока называются стандартными потоками.

Стандартный ввод

Стандартный входной поток обычно передаёт данные от пользователя к программе. Программы, которые предполагают стандартный ввод, обычно получают входные данные от устройства (например, клавиатуры). Стандартный ввод прекращается по достижении EOF (end-of-file, конец файла). EOF указывает на то, что больше данных для чтения нет.

Чтобы увидеть, как работает стандартный ввод, запустите программу cat. Название этого инструмента означает «concatenate» (связать или объединить что-либо). Обычно этот инструмент используется для объединения содержимого двух файлов. При запуске без аргументов cat открывает командную строку и принимает содержание стандартного ввода.

Теперь введите несколько цифр:

1
2
3
ctrl-d

Вводя цифру и нажимая enter, вы отправляете стандартный ввод запущенной программе cat, которая принимает эти данные. В свою очередь, программа cat отображает полученный ввод в стандартном выводе.

Пользователь может задать EOF, нажав ctrl-d, после чего программа cat остановится.

Стандартный вывод

Стандартный вывод записывает данные, сгенерированные программой. Если стандартный выходной поток не был перенаправлен, он выведет текст в терминал. Попробуйте запустить следующую команду для примера:

echo Sent to the terminal through standard output

Команда echo без дополнительных опций отображает на экране все аргументы, переданные ей в командной строке.

Теперь запустите echo без аргументов:

Команда вернёт пустую строку.

Стандартная ошибка

Этот стандартный поток записывает ошибки, создаваемые программой, которая вышла из строя. Как и стандартный вывод, этот поток отправляет данные в терминал.

Рассмотрим пример потока ошибок команды ls. Команда ls отображает содержимое каталогов.

Без аргументов эта команда возвращает содержимое текущего каталога. Если указать в качестве аргумента ls имя каталога, команда вернёт его содержимое.

Поскольку каталога % не существует, команда вернёт стандартную ошибку:

ls: cannot access %: No such file or directory

Перенаправление потоков

Linux предоставляет специальные команды для перенаправления каждого потока. Эти команды записывают стандартный вывод в файл. Если вывод перенаправлен в несуществующий файл, команда создаст новый файл с таким именем и сохранит в него перенаправленный вывод.

Команды с одной угловой скобкой переписывают существующий контент целевого файла:

  • > — стандартный вывод
  • < — стандартный ввод
  • 2> — стандартная ошибка

Команды с двойными угловыми скобками не переписывают содержимое целевого файла:

  • >> — стандартный вывод
  • << — стандартный ввод
  • 2>> — стандартная ошибка

Рассмотрим следующий пример:

cat > write_to_me.txt
a
b
c
ctrl-d

В данном примере команда cat используется для записи выходных данных в файл.

Просмотрите содержимое write_to_me.txt:

cat write_to_me.txt

Команда должна вернуть:

Снова перенаправьте cat в файл write_to_me.txt и введите три цифры.

cat > write_to_me.txt
1
2
3
ctrl-d

Теперь проверьте содержимое файла.

cat write_to_me.txt

Команда должна вернуть:

Как видите, файл содержит только последние выходные данные, поскольку в команде, перенаправляющей выход, использовалась одна угловая скобка.

Теперь попробуйте запустить ту же команду с двумя угловыми скобками:

cat >> write_to_me.txt
a
b
c
ctrl-d

Откройте write_to_me.txt:

1
2
3
a
b
c

Команды с двойными угловыми скобками не перезаписывают существующий контент, а дополняют его.

Конвейеры

Конвейеры (pipes) перенаправляют потоки вывода одной команды на вход другой. При этом данные, передаваемые второй программе, не отображаются в терминале. На экране данные появятся только после обработки второй программой.

Конвейеры в Linux представлены вертикальной чертой.

Например:

Такая команда передаст вывод ls (содержимое текущего каталога) программе less, которая отображает передаваемые ей данные построчно. Как правило, ls выводит содержимое каталогов подряд, не разбивая на строки. Если перенаправить вывод ls в less, то последняя команда разделит вывод на строки.

Как видите, конвейер может перенаправить вывод одной команды на вход другой, в отличие от > и >>, которые перенаправляют данные только в файлы.

Фильтры

Фильтры – это команды, которые могут изменить перенаправление и вывод конвейера.

Примечание : Фильтры также являются стандартными командами Linux, которые можно использовать и без конвейера.

  • find – выполняет поиск файла по имени.
  • grep – выполняет поиск текста по заданному шаблону.
  • tee – перенаправляет стандартный ввод в стандартный вывод и один или несколько файлов.
  • tr – поиск и замена строк.
  • wc – подсчёт символов, строк и слов.

Примеры перенаправления ввода-вывода

Теперь, когда вы ознакомились с основными понятиями и механизмами перенаправления, рассмотрим несколько базовых примеров их использования.

команда > файл

Такой шаблон перенаправляет стандартный вывод команды в файл.

ls ~ > root_dir_contents.txt

Эта команда передает содержимое root каталога системы в качестве стандартного вывода и записывает вывод в файл root_dir_contents. Это удалит все предыдущее содержимое в файле, так как в команде использована одна угловая скобка.

команда > /dev/null

/dev/null – это специальный файл (так называемое «пустое устройство»), который используется для подавления стандартного потока вывода или диагностики, чтобы избежать нежелательного вывода в консоль. Все данные, попадающие в /dev/null, сбрасываются. Перенаправление в /dev/null обычно используется в сценариях оболочки.

ls > /dev/null

Такая команда сбрасывает стандартный выходной поток, возвращаемый командой ls, передав его в /dev/null.

команда 2 > файл

Этот шаблон перенаправляет стандартный поток ошибок команды в файл, перезаписывая его текущее содержимое.

mkdir "" 2> mkdir_log.txt

Эта команда перенаправит ошибку, вызванную неверным именем каталога, и запишет её в log.txt. Обратите внимание: ошибка по-прежнему отображается в терминале.

команда >> файл

Этот шаблон перенаправляет стандартный выход команды в файл, не переписывая текущего содержимого файла.

echo Written to a new file > data.txt
echo Appended to an existing file"s contents >> data.txt

Эта пара команд сначала перенаправляет вводимый пользователем текст в новый файл, а затем вставляет его в существующий файл, не переписывая его содержимого.

команда 2>>файл

Этот шаблон перенаправляет стандартный поток ошибок команды в файл, не перезаписывая существующего содержимого файла. Он подходит для создания логов ошибок программы или сервиса, поскольку содержимое лога не будет постоянно обновляться.

find "" 2> stderr_log.txt
wc "" 2>> stderr_log.txt

Приведенная выше команда перенаправляет сообщение об ошибке, вызванное неверным аргументом find, в файл stderr_log.txt, а затем добавляет в него сообщение об ошибке, вызванной недействительным аргументом wc.

команда | команда

Этот шаблон перенаправляет стандартный выход первой команды на стандартный вход второй команды.

find /var lib | grep deb

Эта команда ищет в каталоге /var и его подкаталогах имена файлов и расширения deb и возвращает пути к файлам, выделяя шаблон поиска красным цветом.

команда | tee файл

Такой шаблон перенаправляет стандартный вывод команды в файл и переписывает его содержимое, а затем отображает перенаправленный выход в терминале. Если указанного файла не существует, он создает новый файл.

В данном шаблоне команда tee, как правило, используется для просмотра вывода программы и одновременного сохранения его в файл.

wc /etc/magic | tee magic_count.txt

Такая команда передаёт количество символов, строк и слов в файле magic (Linux использует его для определения типов файлов) команде tee, которая отправляет эти данные в терминал и в файл magic_count.txt.

команда | команда | команда >> файл

Этот шаблон перенаправляет стандартный вывод первой команды и фильтрует ее через следующие две команды, а затем добавляет окончательный результат в файл.

ls ~ | grep *tar | tr e E >> ls_log.txt

Такая команда отправляет вывод ls для каталога root команде grep. В свою очередь, grep ищет в полученных данных файлы tar. После этого результат grep передаётся команде tr, которая заменит все символы е символом Е. Полученный результат будет добавлен в файл ls_log.txt (если такого файла не существует, команда создаст его автоматически).

Заключение

Функции перенаправления ввода-вывода в Linux сначала кажутся слишком сложными. Однако работа с перенаправлением – один из важнейших навыков системного администратора.

Чтобы узнать больше о какой-либо команде, используйте:

man command | less

Например:

Такая команда вернёт полный список команд для tee.

Tags:

Изучаем Linux, 101

Потоки, программные каналы и перенаправления

Изучение основ работы с конвейерами Linux

Серия контента:

Краткий обзор

Из этой статьи вы узнаете об основных приемах перенаправления стандартных потоков ввода/вывода в Linux. Вы научитесь:

  • Перенаправлять стандартные потоки ввода/вывода: стандартный поток ввода, стандартный поток вывода и стандартный поток ошибок.
  • Направлять вывод одной команды на вход другой команды.
  • Отправлять вывод одновременно на стандартное устройство вывода (stdout) и в файл.
  • Использовать вывод команды в качестве аргументов другой команды.

Эта статья поможет вам подготовиться к сдаче экзамена LPI 101 на администратора начального уровня (LPIC-1) и содержит материалы цели 103.4 темы 103. Цель имеет вес 4.

Об этой серии

Эта серия статей поможет вам освоить задачи администрирования операционной системы Linux. Вы также можете использовать материал этих статей для подготовки к .

Чтобы посмотреть описания статей этой серии и получить ссылки на них, обратитесь к нашему . Этот перечень постоянно дополняется новыми статьями по мере их готовности и содержит самые последние (по состоянию на апрель 2009 года) цели экзаменов сертификации LPIC-1. Если какая-либо статья отсутствует в перечне, можно найти ее более раннюю версию, соответствующую предыдущим целям LPIC-1 (до апреля 2009 года), обратившись к нашим .

Необходимые условия

Чтобы извлечь наибольшую пользу из наших статей, необходимо обладать базовыми знаниями о Linux и иметь работоспособный компьютер с Linux, на котором можно будет выполнять все встречающиеся команды. Иногда различные версии программ выводят результаты по-разному, поэтому содержимое листингов и рисунков может отличаться от того, что вы увидите на вашем компьютере.

Подготовка к выполнению примеров

Как связаться с Яном

Ян – один из наших наиболее популярных и плодовитых авторов. Ознакомьтесь со (EN), опубликованными на сайте developerWorks. Вы можете найти контактные данные в и связаться с ним, а также с другими авторами и участниками ресурса My developerWorks.

Для выполнения примеров в этой статье мы будем использовать некоторые файлы, созданные ранее в статье " ". Если вы не читали эту статью или не сохранили эти файлы, не расстраивайтесь! Давайте начнем с создания новой директории lpi103-4 и всех необходимых файлов. Для этого откройте текстовое окно и перейдите в вашу домашнюю директорию. Скопируйте содержимое листинга 1 в текстовое окно; в результате выполнения команд в вашей домашней директории будет создана поддиректория lpi103-4 и все необходимые файлы в ней, которые мы и будем использовать в наших примерах.

Листинг 1. Создание файлов, необходимых для примеров этой статьи
mkdir -p lpi103-4 && cd lpi103-4 && { echo -e "1 apple\n2 pear\n3 banana" > text1 echo -e "9\tplum\n3\tbanana\n10\tapple" > text2 echo "This is a sentence. " !#:* !#:1->text3 split -l 2 text1 split -b 17 text2 y; }

Ваше окно должно выглядеть так, как показано в листинге 2, а вашей текущей рабочей директорией должна стать вновь созданная директория lpi103-4.

Листинг 2. Результаты создания необходимых файлов
$ mkdir -p lpi103-4 && cd lpi103-4 && { > echo -e "1 apple\n2 pear\n3 banana" > text1 > echo -e "9\tplum\n3\tbanana\n10\tapple" > text2 > echo "This is a sentence. " !#:* !#:1->text3echo "This is a sentence. " "This is a sentence. " "This is a sentence.">text3 > split -l 2 text1 > split -b 17 text2 y; } $

Перенаправление стандартного ввода/вывода

Командный интерпретатор Linux, такой как Bash, получает входные данные и направляет выходные данные в виде последовательностей или потоков символов. Любой символ не зависит ни от предыдущих, ни от последующих символов. Символы не упорядочены в виде структурированных записей или блоков с фиксированным размером. Доступ к потокам осуществляется с помощью механизмов ввода/вывода независимо от того, откуда поступают и куда передаются потоки символов (файл, клавиатура, окно, экран или другое устройство ввода/вывода). Командные интерпретаторы Linux используют три стандартных потока ввода/вывода, каждому из которых назначен определенный файловый дескриптор.

  1. stdout стандартный поток вывода , отображает вывод команд и имеет дескриптор 1.
  2. stderr стандартный поток ошибок , отображает ошибки команд и имеет дескриптор 2.
  3. stdin стандартный поток ввода , передает входные данные командам и имеет дескриптор 0.

Потоки ввода обеспечивают передачу входных данных (обычно поступающих с клавиатуры) командам. Потоки вывода обеспечивают печать текстовых символов, как правило, на терминал. Изначально терминал представлял собой ASCII печатающее устройство или дисплейный терминал, но сейчас, как правило, это просто окно на рабочем столе компьютера.

Если вы уже прочитали руководство " ", то часть материала из этой статьи окажется вам знакомой.

Перенаправление вывода

Существует два способа перенаправления вывода в файл:

n > перенаправляет вывод из файлового дескриптора n в файл. Вы должны иметь права на запись в файл. Если файла не существует, то он будет создан. Если файл существует, то все его содержимое, как правило, уничтожается без каких-либо предупреждений. n >> также перенаправляет вывод из файлового дескриптора n в файл. Вы также должны иметь права на запись в файл. Если файла не существует, то он будет создан. Если файл существует, то вывод добавляется к его содержимому.

Символ n в операторах n> или n>> является файловым дескриптором . Если он не указан, то предполагается, что используется стандартное устройство вывода. В листинге 3 продемонстрирована операция перенаправления для разделения стандартного потока вывода и стандартного потока ошибок команды ls с использованием файлов, которые были созданы ранее в директории lpi103-4. Также продемонстрировано добавление вывода команды в существующие файлы.

Листинг 3. Перенаправление вывода
$ ls x* z* ls: cannot access z*: No such file or directory xaa xab $ ls x* z* >stdout.txt 2>stderr.txt $ ls w* y* ls: cannot access w*: No such file or directory yaa yab $ ls w* y* >>stdout.txt 2>>stderr.txt $ cat stdout.txt xaa xab yaa yab $ cat stderr.txt ls: cannot access z*: No such file or directory ls: cannot access w*: No such file or directory

Мы уже говорили, что перенаправление вывода с помощью оператора n> обычно приводит к перезаписи существующих файлов. Вы можете управлять этим свойством при помощи опции noclobber встроенной команды set . Если эта опция определена, то вы можете переопределить ее с помощью оператора n>|, как показано в листинге 4.

Листинг 4. Перенаправление вывода с помощью опции noclobber
$ set -o noclobber $ ls x* z* >stdout.txt 2>stderr.txt -bash: stdout.txt: cannot overwrite existing file $ ls x* z* >|stdout.txt 2>|stderr.txt $ cat stdout.txt xaa xab $ cat stderr.txt ls: cannot access z*: No such file or directory $ set +o noclobber #restore original noclobber setting

Иногда может потребоваться перенаправить в файл как стандартный вывод, так и стандартный поток ошибок. Часто это используется в автоматизированных процессах или фоновых заданиях для того, чтобы впоследствии можно было просмотреть результаты работы. Чтобы перенаправить стандартный вывод и стандартный поток ошибок в одно и то же место, используйте оператор &> или &>>. Альтернативный вариант – перенаправить файловый дескриптор n и затем файловый дескриптор m в одно и то же место с помощью конструкции m>&n или m>>&n. В этом случае важен порядок перенаправления потоков. Например, команда
command 2>&1 >output.txt
это не то же самое, что команда
command >output.txt 2>&1
В первом случае поток ошибок stderr перенаправляется в текущее месторасположение потока stdout, а затем поток stdout перенаправляется в файл output.txt; однако второе перенаправление затрагивает только stdout, но не stderr. Во втором случае поток stderr перенаправляется в текущее месторасположение потока stdout, то есть, в файл output.txt. Эти перенаправления проиллюстрированы в листинге 5. Обратите внимание на последнюю команду, в которой стандартный вывод был перенаправлен после стандартного потока ошибок, и, как следствие, поток ошибок продолжает выводиться в окно терминала.

Листинг 5. Перенаправление двух потоков в один файл
$ ls x* z* &>output.txt $ cat output.txt ls: cannot access z*: No such file or directory xaa xab $ ls x* z* >output.txt 2>&1 $ cat output.txt ls: cannot access z*: No such file or directory xaa xab $ ls x* z* 2>&1 >output.txt # stderr does not go to output.txt ls: cannot access z*: No such file or directory $ cat output.txt xaa xab

В других ситуациях вам может потребоваться полностью проигнорировать стандартный вывод или стандартный поток ошибок. Для этого следует перенаправить соответствующий поток в пустой файл /dev/null. В листинге 6 показано, как проигнорировать поток ошибок команды ls и как с помощью команды cat убедиться в том, что файл /dev/null на самом деле пуст.

Листинг 6. Игнорирование стандартного потока ошибок посредством использования /dev/null
$ ls x* z* 2>/dev/null xaa xab $ cat /dev/null

Перенаправление ввода

Так же, как мы можем перенаправить потоки stdout и stderr, мы можем перенаправить поток stdin из файла с помощью оператора <. Если вы прочли руководство " ", то должны помнить, что в разделе была использована команда tr для замены пробелов в файле text1 на символы табуляции. В том примере мы использовали вывод команды cat чтобы создать стандартный поток ввода для команды tr . Теперь для преобразования пробелов в символы табуляции вместо бесполезного вызова команды cat мы можем использовать перенаправление ввода, как показано в листинге 7.

Листинг 7. Перенаправление ввода
$ tr " " "\t"

В командных интерпретаторах, в том числе и в bash, реализована концепция here-document , которая является одним из способов перенаправления ввода. В ней используется конструкция << и какое-либо слово, например END, являющееся маркером, или сигнальной меткой, означающей конец ввода. Эта концепция продемонстрирована в листинге 8.

Листинг 8. Перенаправление ввода с использованием концепции here-document
$ sort -k2 < 1 apple > 2 pear > 3 banana > END 1 apple 3 banana 2 pear

Но почему нельзя просто набрать команду sort -k2 , ввести данные и нажать комбинацию Ctrl-d , означающую конец ввода? Разумеется, вы могли бы выполнить эту команду, но тогда вы не узнали бы о концепции here-document, которая очень часто используется в сценариях командной оболочки (в которых не существует другой возможности указать, какие именно строки должны восприниматься в качестве ввода). Поскольку для выравнивания текста и обеспечения удобства чтения в сценариях широко используются символы табуляции, существует другой прием использования концепции here-document. При использовании оператора <<- вместо оператора << начальные символы табуляции удаляются.

В листинге 9 мы использовали подстановку команд для создания символа табуляции, а затем создали небольшой сценарий командной оболочки, содержащий две команды cat , каждая из которых считывает данные из блока here-document. Заметьте, что мы использовали слово END в качестве сигнальной метки блока here-document, который мы считываем с терминала. Если бы мы использовали это же слово в нашем сценарии, то наш ввод закончился бы преждевременно. Поэтому вместо слова END мы используем в сценарии слово EOF. После того, как наш сценарий создан, мы используем команду. (точка) чтобы запустить его в контексте текущего командного интерпретатора.

Листинг 9. Перенаправление ввода с использованием концепции here-document
$ ht=$(echo -en "\t") $ cat<ex-here.sh > cat <<-EOF > apple > EOF > ${ht}cat <<-EOF > ${ht}pear > ${ht}EOF > END $ cat ex-here.sh cat <<-EOF apple EOF cat <<-EOF pear EOF $ . ex-here.sh apple pear

В следующих статях этой серии вы узнаете больше о подстановке команд и сценариях. Ссылки на все статьи этой серии вы можете найти в .

Создание конвейеров

Использование команды xargs

Команда xargs считывает данные со стандартного устройства ввода, а затем строит и выполняет команды, параметрами которых являются полученные входные данные. Если не указана никакая команда, то используется команда echo . В листинге 12 приведен простой пример использования нашего файла text1, содержащего три строки по два слова в каждой.

Листинг 12. Использование команды xargs
$ cat text1 1 apple 2 pear 3 banana $ xargs

Почему же тогда вывод xargs содержит только одну строку? По умолчанию xargs разбивает входные данные, если встречает символы-разделители, и каждый полученный фрагмент становится отдельным параметром. Однако когда xargs строит команду, ей за один раз передается максимально возможное количество параметров. Это поведение можно изменить с помощью параметра –n или --max-args . В листинге 13 приведен пример использования обоих вариантов; также был выполнен явный вызов команды echo для использования с xargs .

Листинг 13. Использование команд xargs и echo
$ xargs" args > 1 apple 2 pear 3 banana $ xargs --max-args 3 " args > 1 apple 2 args > pear 3 banana $ xargs -n 1 " args > 1 args > apple args > 2 args > pear args > 3 args > banana

Если входные данные содержат пробелы, но при этом они заключены в одиночные или двойные кавычки (либо пробелы представлены в виде escape-последовательностей с использованием обратной косой черты), то xargs не будет разбивать их на отдельные части. Это показано в листинге 14.

Листинг 14. Использование команды xargs и кавычек
$ echo ""4 plum"" | cat text1 - 1 apple 2 pear 3 banana "4 plum" $ echo ""4 plum"" | cat text1 - | xargs -n 1 1 apple 2 pear 3 banana 4 plum

До сих пор все аргументы добавлялись в конец команды. Если вам необходимо, чтобы после них были добавлены другие дополнительные аргументы, то воспользуйтесь опцией -I для указания строки замещения. В том месте вызываемой через xargs команды, в котором используется строка замещения, вместо нее будет подставлен аргумент. При использовании такого подхода каждой команде передается только один аргумент. Однако аргумент будет создан из целой входной строки, а не из отдельного ее фрагмента. Также вы можете использовать опцию -L команды xargs , в результате чего в качестве аргумента будет использоваться вся строка целиком, а не отдельные ее фрагменты, разделенные пробелами. Использование опции -I неявно вызывает использование опции -L 1 . В листинге 15 приведены примеры использования опций -I и –L .

Листинг 15. Использование команды xargs и строк ввода
$ xargs -I XYZ echo "START XYZ REPEAT XYZ END" " <9 plum> <3 banana><3 banana> <10 apple><10 apple> $ cat text1 text2 | xargs -L2 1 apple 2 pear 3 banana 9 plum 3 banana 10 apple

Хотя в наших примерах используются простые текстовые файлы, вы не будете часто использовать команду xargs для таких случаев. Как правило, вы будете иметь дело с большим списком файлов, полученных в результате выполнения таких команд, как ls , find или grep . В листинге 16 показан один из способов передачи через xargs списка содержимого директории такой команде, как, например, grep .

Листинг 16. Использование команды xargs и списка файлов
$ ls |xargs grep "1" text1:1 apple text2:10 apple xaa:1 apple yaa:1

Что произойдет в последнем примере, если одно или несколько имен файлов будут содержать пробелы? Если вы попытаетесь использовать команду так, как это было сделано в листинге 16, то вы получите ошибку. В реальной ситуации список файлов может быть получен не от команды ls , а, например, в результате выполнения пользовательского сценария или команды; а может быть, вы захотите обработать его на других этапах конвейера с целью дополнительной фильтрации. Поэтому мы не берем во внимание тот факт, что вы могли бы просто использовать команду grep "1" * вместо существующей логической структуры.

В случае с командой ls вы могли бы использовать опцию --quoting-style для того, чтобы имена файлов, содержащие пробелы, были заключены в скобки (или представлены в виде escape-последовательностей). Лучшим решением (когда это возможно) является использование опции -0 команды xargs , в результате чего для разделения входных аргументов используются пустые символы (\0). Хотя команда ls не имеет опции, позволяющей использовать в качестве вывода имена файлов с завершающим нулем, многие команды умеют делать это.

В листинге 17 мы сначала скопируем файл text1 в "text 1", а затем приведем несколько примеров использования списка имен файлов, содержащих пробелы, с командой xargs . Эти примеры позволяют понять саму идею, поскольку полностью освоить работу с xargs может оказаться не так просто. В частности, последний пример преобразования символов новой строки в пустые символы не сработал бы в том случае, если некоторые имена файлов уже содержали бы символы новой строки. В следующем разделе этой статьи мы рассмотрим более надежное решение с применением команды find для генерации подходящего вывода, в котором в качестве разделителей используются пустые символы.

Листинг 17. Использование команды xargs и файлов, содержащих пробелы в именах
$ cp text1 "text 1" $ ls *1 |xargs grep "1" # error text1:1 apple grep: text: No such file or directory grep: 1: No such file or directory $ ls --quoting-style escape *1 text1 text\ 1 $ ls --quoting-style shell *1 text1 "text 1" $ ls --quoting-style shell *1 |xargs grep "1" text1:1 apple text 1:1 apple $ # Illustrate -0 option of xargs $ ls *1 | tr "\n" "\0" |xargs -0 grep "1" text1:1 apple text 1:1 apple

Команда xargs не может строить сколь угодно длинные команды. Так, в Linux до версии ядра 2.26.3 максимальная длина команды была ограничена. Если вы попытаетесь выполнить такую команду, как, например, rm somepath/* , а директория содержит множество файлов с длинными именами, то выполнение может завершиться ошибкой, сообщающей, что список аргументов слишком длинный. Если вы работаете с более старыми версиями Linux или UNIX, в которых могут присутствовать такие ограничения, то будет полезно узнать, как можно использовать xargs таким образом, чтобы обойти их.

Вы можете использовать опцию --show-limits для просмотра ограничений, установленных по умолчанию для команды xargs , и опцию -s – для задания максимальной длины выводимых команд. Об остальных опциях вы можете узнать из man-страниц.

Использование команды find с опцией -exec или совместно с командой xargs

Из руководства " " вы узнали о том, как использовать команду find для поиска файлов на основе их имен, времени модификации, размера и прочих характеристик. Обычно над найденными файлами необходимо выполнять определенные действия – удалять, копировать, переименовывать их и так далее. Сейчас мы рассмотрим опцию -exec команды find , работа которой похожа на работу команды find с последующей передачей вывода команде xargs .

Листинг 18. Использование команды find с опцией -exec
$ find text -exec cat text3 {} \; This is a sentence. This is a sentence. This is a sentence. 1 apple 2 pear 3 banana This is a sentence. This is a sentence. This is a sentence. 9 plum 3 banana 10 apple

Сопоставив результаты листинга 18 с тем, что вам уже известно о xargs , можно обнаружить несколько различий.

  1. Вы должны использовать в команде символы {} для указания места подстановки, в которое будет подставлено имя файла. Эти символы не добавляются автоматически в конце команды.
  2. Вы должны завершить команду точкой с запятой, которая должна быть представлена в виде escape-последовательности (\;, ";" или ";").
  3. Команда выполняется один раз для каждого входного файла.

Попробуйте самостоятельно выполнить команду find text |xargs cat text3 , чтобы увидеть различия.

Теперь давайте вернемся к случаю, когда имя файла содержит пробелы. В листинге 19 мы попытались использовать команду find с опцией -exec вместо команд ls и xargs .

Листинг 19. Использование команды find с опцией -exec и файлов, содержащих пробелы в именах
$ find . -name "*1" -exec grep "1" {} \; 1 apple 1 apple

Пока все хорошо. Однако не кажется ли вам, что чего-то здесь не хватает? В каких файлах присутствовали строки, найденные при помощи grep ? Здесь не хватает имен файлов, поскольку find вызывает grep один раз для каждого файла, а grep , будучи умной командой, знает о том, что если ей было передано имя лишь одного файла, то нет необходимости сообщать вам о том, что это был за файл.

В этой ситуации мы могли бы воспользоваться командой xargs , однако мы уже знаем о проблеме с файлами, имена которых содержат пробелы. Также мы упоминали тот факт, что команда find может генерировать список имен с пустыми разделителями, благодаря опции -print0 . Современные версии команды find могут разделяться не точкой с запятой, а знаком +, благодаря чему, за один вызов команды find можно передать максимально возможное число имен, так же, как и в случае использования xargs . Излишне говорить о том, что в этом случае вы можете использовать конструкцию {} только один раз, и что она должна являться последним параметром команды. В листинге 20 продемонстрированы оба этих метода.

Листинг 20. Использование команд find , xargs и файлов, содержащих пробелы в именах
$ find . -name "*1" -print0 |xargs -0 grep "1" ./text 1:1 apple ./text1:1 apple $ find . -name "*1" -exec grep "1" {} + ./text 1:1 apple ./text1:1 apple

Оба этих метода являются рабочими и выбор какого-то одного из них часто обусловлен лишь личными предпочтениями пользователя. Помните о том, что передавая по конвейеру объекты с необработанными символами-разделителями и пробелами, вы можете столкнуться с проблемами; поэтому если вы передаете вывод команде xargs , то используйте опцию -print0 команды find , а также опцию -0 команды xargs , которая сообщает, что во входных данных используются пустые разделители. Другие команды, включая tar , также поддерживают опцию -0 и работу с входными данными, содержащими пустые разделители, поэтому всегда следует использовать эту опцию для тех команд, которые ее поддерживают, если только вы уверены на все 100%, что входной список не создаст вам проблем.

Наш последний комментарий затрагивает работу со списком файлов. Хорошей идеей будет всегда тщательно проверять ваш список и команды, прежде чем выполнять пакетные операции (например, удаление или переименование множества файлов). Наличие актуальной резервной копии в нужный момент также может оказаться неоценимым.

Разделение вывода

В завершение этой статьи мы кратко рассмотрим еще одну команду. Иногда может возникнуть необходимость просматривать вывод на экране и одновременно сохранять его в файл. Для этого вы могли бы перенаправить вывод команды в файл в одном окне, а затем с помощью tail -fn1 отслеживать вывод в другом окне, однако проще всего использовать команду tee .

Команда tee используется в конвейере, а ее аргументом является имя файла (или имена нескольких файлов), в который будет передаваться стандартный вывод. Опция -a позволяет не замещать старое содержимое файла новым содержимым, а добавлять данные в конец файла. Как уже говорилось при рассмотрении конвейеризации, если вы хотите сохранить как стандартный вывод, так и поток ошибок, то необходимо перенаправлять поток stderr в поток stdout прежде, чем передавать данные на вход команде tee . В листинге 21 приведен пример использования команды tee для сохранения вывода в два файла, f1 и f2.

Листинг 21. Разделение потока stdout с помощью команды tee
$ ls text|tee f1 f2 text1 text2 text3 $ cat f1 text1 text2 text3 $ cat f2 text1 text2 text3

Операторы перенаправления команд используются для изменения местоположений потоков ввода и вывода команд, заданных по умолчанию, на какие-либо другие. Местоположение потоков ввода и вывода называется дескриптор.

В следующей таблице описаны операторы перенаправления потоков ввода и вывода команд.

Оператор перенаправления Описание
> Записывает данные на выходе команды вместо командной строки в файл или на устройство, например, на принтер.
< Читает поток входных данных команды из файла, а не с клавиатуры.
>> Добавляет выходные данные команды в конец файла, не удаляя при этом существующей информации из файла.
>& Считывает данные на выходе одного дескриптора как входные данные для другого дескриптора.
<& Считывает входные данные одного дескриптора как выходные данные другого дескриптора.
| Считывает выходные данные одной команды и записывает их на вход другой команды. Эта процедура известна под названием «канал».

По умолчанию, входные данные команды (дескриптор STDIN) отсылаются с клавиатуры интерпретатору команд Cmd.exe, далее Cmd.exe отправляет выходные данные команды (дескриптор STDOUT) в окно командной строки.

В следующей таблице представлены доступные дескрипторы.

Номера от 0 до 9 представляют первые 10 дескрипторов. Для запуска программы и перенаправления любого из 10 дескрипторов используется интерпретатор команд Cmd.exe. Для задания требуемого дескриптора перед оператором перенаправления введите его номер. Если дескриптор не определен, то по умолчанию оператором перенаправления ввода «<» будет ноль (0), а оператором перенаправления вывода «>» будет единица (1). После ввода оператора «<» или «>» необходимо указать, откуда читать и куда записывать данные. Можно задать имя файла или любой из существующих дескрипторов.

Для задания перенаправления в существующие дескрипторы используется амперсанд (&), затем номер требуемого дескриптора (например, & номер_дескриптора ). Например, для перенаправления дескриптора 2 (STDERR) в дескриптор 1 (STDOUT) введите:

Дублирование дескрипторов

Оператор перенаправления «&» дублирует выходные или входные данные с одного заданного дескриптора на другой заданный дескриптор. Например, для отправки выводных данных команды dir в файл File.txt и отправки ошибки вывода в файл File.txt введите:

dir>c:\file.txt 2>&1

При дублировании дескриптора происходит копирование всех его исходных характеристик. Например, если дескриптор доступен только для записи, то все его дубликаты будут доступны только для записи. Нельзя продублировать дескриптор с доступом только для чтения в дескриптор с доступом только для записи.

Перенаправление ввода команд (<)

Для перенаправления ввода команд с цифровой клавиатуры на файл или на устройство используйте оператор «<». Например, для ввода команды sort из файла List.txt введите:

sort

Содержимое файла File.txt появится в командной строке в виде списка в алфавитном порядке.

Оператор «<» открывает заданное имя файла с доступом только для чтения. Поэтому с его помощью нельзя записывать в файл. Например, при запуске программы с оператором <&2 все попытки прочитать дескриптор 0 ни к чему не приведут, так как изначально он был открыт с доступом только для записи.

Примечание

  • Дескриптор 0 задан по умолчанию для оператора перенаправления ввода «<».

Перенаправление вывода команд (>)

Выходные данные практически всех команд высвечиваются в окне командной строки. Даже команды, выводящие данные на диск или принтер, выдают сообщения и запросы в окне командной строки.

Для перенаправления вывода команд из окна командной строки в файл или на устройство применяется оператор «>». Этот оператор используется с большинством команд. Например, для перенаправления вывода команды dir в файл Dirlist.txt введите:

dir>dirlist.txt

Если файл Dirlist.txt не существует, интерпретатор команд Cmd.exe создаст его. Если файл существует, Cmd.exe заменит информацию в файле на данные, полученные от команды dir .

Для запуска команды netsh routing dump и последующей отправки результатов ее работы в Route.cfg введите:

netsh routing dump > c:\route.cfg

Оператор «>» открывает заданный файл с доступом только для записи. Поэтому с помощью данного оператора файл прочитать нельзя. Например, при запуске программы с оператором перенаправления <&0 все попытки записать дескриптор 1 ни к чему не приведут, так как изначально дескриптор 0 был открыт с доступом только для чтения.

Примечание.

  • Дескриптор 1 задан по умолчанию для оператора перенаправления вывода «>».

Использование оператора «<&» для перенаправления ввода и дублирования

Для использования оператора перенаправления ввода необходимо, чтобы задаваемый файл уже существовал. Если файл для ввода существует, то интерпретатор команд Cmd.exe открывает его с доступом только для чтения и его содержимое отправляет в команду так, как если бы это был ввод с цифровой клавиатуры. При задании дескриптора интерпретатор команд Cmd.exe дублирует его в дескриптор, существующий в системе.

Например, для считывания файла File.txt на вход в дескриптор 0 (STDIN) введите:

Для открытия файла File.txt, сортировки его содержимого и последующей отправки в окно командной строки (STDOUT) введите:

sort< file.txt

Для того чтобы найти файл File.txt и перенаправить дескриптор 1 (STDOUT) и дескриптор 2 (STDERR) в Search.txt введите:

findfile file.txt>search.txt 2<&1

Для дублирования определенного пользователем дескриптора 3 в качестве входной информации для дескриптора 0 (STDIN) введите:

Использование оператора «>&» для перенаправления ввода и дублирования

При перенаправлении вывода в файл и задании существующего имени файла интерпретатор команд Cmd.exe открывает файл с доступом только для записи и переписывает его содержимое. Если дескриптор задан, интерпретатор команд Cmd.exe дублирует файл в существующий дескриптор.

Для дублирования определенного пользователем дескриптора 3 в дескриптор 1 введите:


Для перенаправления всех выходных данных, включая выходные данные дескриптора 2 (STDERR), команды ipconfig в дескриптор 1 (STDOUT) и последующего перенаправления выходных данных в Output.log введите:


ipconfig.exe>>output.log 2>&1

Использование оператора «>>» для добавления вывода

Для добавления выходных данных команды в конец файла без потери хранящейся в нем информации используется двойной символ «больше» (>>). Например, следующая команда добавляет список каталогов, созданный командой dir , в файл Dirlist.txt:


dir>>dirlist.txt

Для добавления выходных данных команды netstat в конец файла Tcpinfo.txt введите:


netstat>>tcpinfo.txt

Иногда удобнее записывать это следующим образом:

SET OutFile="%~n0.html" > %OutFile% ECHO ^ >> %OutFile% ECHO ^ >> %OutFile% ECHO ^best page^ >> %OutFile% ECHO ^ >> %OutFile% ECHO ^ >> %OutFile% ECHO Hello World >> %OutFile% ECHO ^ >> %OutFile% ECHO ^

Использование оператора канала (|)

Оператор канала «вертикальная линия» (|) забирает выходные данные одной команды (по умолчанию STDOUT) и направляет их на вход другой команды (по умолчанию STDIN). Например, следующая команда сортирует каталог:

В данном примере обе команды запускаются одновременно, но команда sort приостанавливает работу до получения выходных данных команды dir . Команда sort использует выходные данные команды dir в качестве своих входных данных, а затем свои выходные данные отправляет в дескриптор 1 (STDOUT).

Комбинирование команд с операторами перенаправления

Комбинируя команды-фильтры с другими командами и именами файлов, можно создавать команды на заказ. Например, для сохранения имен файлов, содержащих строку «LOG», используется следующая команда:

dir /b | find "LOG" > loglist.txt

Выход команды dir отсылается в команду-фильтр find . Имена файлов, содержащие строку «LOG», хранятся в файле Loglist.txt в виде списка (например, NetshConfig.log, Logdat.svd и Mylog.bat).

При использовании более одного фильтра в одной команде их необходимо отделять с помощью канала (|). Например, следующая команда ищет в каждом каталоге диска C файлы, в названии которых присутствует строка «Log», и выводит их постранично на экран:

dir c:\ /s /b | find "LOG" | more

Наличие канала (|) указывает cmd.exe , что выход команды DIR нужно отправить команде-фильтру find . Команда find выбирает только те имена файлов, в которых содержится строка «LOG». Команда more выводит на экран имена файлов, полученные командой find с паузой после заполнения каждого экрана. Дополнительные сведения о командах-фильтрах смотри в разделе