печатает сообщение, которое следует за строкой "what". Чтобы идентифи-
цировать версию данного командного файла, наберите

# what tree

и будет напечатано следующее сообщение:

tree:
tree v1.0 Visual display of a file tree Author: Russ Sage

Строки 4-7 проверяют, не слишком ли много аргументов было переда-
но командной строке. Это осуществляется путем исследования переменной
$#, которая представляет собой счетчик числа позиционных параметров
командной строки. Если насчитывается более одного параметра, печата-
ется соответствующее сообщение об ошибке в стандартный файл ошибок
(stderr) и программа останавливается с плохим значением статуса.
Отметим, что команда echo обычно печатает в стандартный выход
(stdout). Мы можем перенаправить stdout в другой файловый дескриптор,
указав его. В данном случае мы собираемся печатать в stderr. Синтаксис
переводится так: "вывести эту строку и перенаправить ее в файловый
дескриптор (&) стандартного файла ошибок (2)". Печать сообщений об
ошибках в stderr обеспечивает согласованное поведение командного файла
независимо от среды, в которой он запущен.
Отметим также, что коды статуса выхода в интерпретаторе shell
противоположны тем, которые используются при программировании на языке
Си. В Си истинное значение есть 1, ложное отлично от 1. При программи-
ровании на языке shell успешным статусом выхода (истиной) является 0,
а плохим статусом (ложью) ненулевое значение.
Вы, возможно, удивитесь, почему мы так беспокоимся о том, чтобы
вернуть ложный статус выхода, если командный файл собирается просто
напечатать сообщение об ошибке и прекратить работу. Дело в том, что
все инструментальные средства системы UNIX должны быть спроектированы
так, чтобы они могли быть связаны с другими командами и процессами, в
которые они могут быть встроены. Возможно, что другой команде необхо-
димо будет вызвать команду tree и проверить, корректно ли она отрабо-
тала. Хорошим стилем проектирования программных средств является прог-
нозирование и разрешение многих способов использования программы.
Строки 9-15 проверяют, чтобы любые параметры, передаваемые ко-
мандной строке, были действительно каталогами, как указано в нашем
синтаксисе. Напомним, что в командной строке может быть помещен только
один каталог. Если мы используем только один параметр и этот параметр
не является каталогом, то мы печатаем сообщение об ошибке и выходим.
Таким образом, операторы проверки гарантируют, что либо не использу-
ется ни один параметр, либо единственный используемый параметр явля-
ется корректным каталогом.
Мы подошли к сердцу команды tree - это строки 17-20. Главным
здесь является команда find системы UNIX. Каталог, в котором ведется
поиск, определяется при запуске команды. Синтаксис ${1:-.} является
формой параметрической подстановки и означает следующее: если $1 (что
является первым позиционным параметром) установлен (иными словами,
если аргумент был передан командной строке и был ненулевым), то нужно
использовать это значение. В противном случае следует использовать ка-
талог . (текущий каталог). Этот тип подстановки дает нам возможность
запускать команду tree без указания имени каталога (когда после tree
на командной строке ничего не следует),- то есть работать в режиме "по
умолчанию", что часто используется в различных файловых инструментах.
Команда find выводит на печать полное имя каждого файла, который
ей встречается. Поскольку не используется никакая специальная опция
для селекции файлов, печатаются все имена. После этого все полные име-
на файлов сортируются для более удобного чтения. Такая сортировка
несколько увеличивает время работы команды, однако наглядность резуль-
тата говорит о том, что это время было потрачено с пользой.
Далее, отсортированные полные имена файлов передаются по прог-
раммному каналу команде sed системы Unix. Sed - это "потоковый редак-
тор", очень гибкое средство, которое может быть использовано для иден-
тификации и обработки различных образцов текста. Опции -e являются
операциями редактирования, применяемыми к поступающим данным. Первый
оператор просто сообщает команде sed, что нужно напечатать первую
строку, затем удалить строку 1. Это делается для того, чтобы напеча-
тать название корневого каталога, который исследуется. Этой строке не
требуется никакой дальнейшей модификации, так как корневой каталог не
имеет никаких дополнительных элементов путей доступа, которые нужно
было бы трансформировать в символы косой черты для показа отступов.
Удаление первой строки связано с тем, что она не нужна в дальнейшей
работе.
Вторая операция редактирования является командой подстановки. Она
заменяет каждый символ, отличный от символа косой черты (вплоть до
первого символа /) на последовательность пробелов и затем один символ
(/). Это избавляет нас от печатания имен промежуточных каталогов впе-
реди полного имени файла. Буква g в конце этой строки означает, что
эта операция выполняется глобально, то есть для всех считываемых сим-
волов. Итак, теперь строка состоит из начального элемента пути и одной
или более последовательностей пробелов, разделенных символами косой
черты. Символы обратной косой черты (\) в конце операций редактирова-
ния - это символы продолжения, которые сообщают команде sed, что нужно
продолжить работу со следующей строкой в текущем пакете операций ре-
дактирования.
Третья операция редактирования (строка 19) также является коман-
дой подстановки и заменяет каждый символ, который не является пробелом
(вплоть до символа /) на "не символ" и один символ косой черты. Этот
оператор удаляет пробелы из предыдущего результата редактирования и
смещает символ в самую левую позицию. Это создает гнездовую индикацию,
которую мы видели в предыдущем примере.
Последняя операция редактирования (в строке 20) заменяет символ
косой черты и все отличные от него символы (до конца строки) просто на
символы, отличные от /. Отметим, что это устраняет самый правый символ
/, который присутствует в листинге команды find. В результате остается
имя подчиненного файла, сдвинутое вправо.
Отметим синтаксис \1 команды sed - признак, относящийся к первому
(в данном случае единственному) регулярному выражению в скобках, кото-
рое ему предшествует. В данном случае команде sed указано пройти сим-
волы, соответствующие регулярному выражению - символы, отличные от /.

2.1.2. thead - печать начала каждого файла

-----------------------------------------------------
ИМЯ: thead
-----------------------------------------------------

thеаd Печатает заголовок (первые несколько строк) файлов.

    НАЗНАЧЕНИЕ



Пройти файловое дерево и напечатать первые несколько строк каждо-
го файла. Если не указан каталог, то thead действует как фильтр.


    ФОРМАТ ВЫЗОВА



thead [dir...]

    ПРИМЕР ВЫЗОВА



$ find $HOME/src -name "*.c" -print | sort | thead

Печатает заголовки (первые несколько строк) всех моих исходных
файлов на языке Си.

    ТЕКСТ ПРОГРАММЫ



1 :
2 # @(#) thead v1.0 Prints head of files in tree Author: Russ Sage
2а Печатает заголовки файлов в дереве

4 if [ "`echo $1|cut -c1`" = "-" ]
5 then echo "$0: arg error"
6 echo "usage: $0 [dir ...]"
7 exit 1
8 fi

10 case $# in
11 0) while read FILE
12 do
13 if file $FILE | fgrep text >/dev/null 2>&1
14 then echo "\n:::::::::::::::::::::"
15 echo " $FILE"
16 echo "\n:::::::::::::::::::::"
17 head -15 $FILE
18 fi
19 done;;
20 *) for NAME in $*
21 do
22 find $NAME -type f -print | sort | wile read FILE
23 do
24 if file $FILE | fgrep text >/dev/null 2>&1
25 then echo "\n:::::::::::::::::::::"
26 echo " $FILE"
27 echo "\n:::::::::::::::::::::"
28 head -15 $FILE
29 fi
30 done
31 done;;
32 esac

    ПЕРЕМЕННЫЕ СРЕДЫ ВЫПОЛНЕНИЯ



FILE Содержит имя каждого файла
NAME Имя каталога, заданное в командной строке


ОПИСАНИЕ

ЗАЧЕМ НУЖЕН КОМАНДНЫЙ ФАЙЛ thead?

Как уже объяснялось ранее в этой главе, иерархическая файловая
система является очень значительной частью системы UNIX. Однако, толь-
ко несколько команд в UNIX имеют дело непосредственно с рекурсивным
поиском файлов. Единственный способ расширить возможности системы -
создать новые рекурсивные утилиты, работающие с файлами. В данном слу-
чае мы соединим нашу стратегию поиска по дереву с командой head систе-
мы UNIX для упрощения идентификации содержимого всех файлов в выделен-
ном сегменте файлового дерева.
Иногда у нас, возможно, будет возникать желание просмотреть файлы
в более чем одном каталоге. В больших проектах разработки программного
обеспечения файлы обычно создаются в нескольких иерархических катало-
гах. Thead может работать со множеством путей доступа и выводить заго-
ловки (несколько первых строк файлов) в виде непрерывного потока.

ЧТО ДЕЛАЕТ thead?

Thead - это препроцессорная команда к команде head системы UNIX.
Команда head очень примитивна, но, добавляя к ней управляющую структу-
ру и логику, мы можем создать очень полезное инструментальное
средство, которого нет в стандартной среде UNIX.
Например, мы захотели просмотреть заголовки всех текстовых файлов
в нашем регистрационном каталоге. Если у нас имеется большое число
подкаталогов, нам необходимо все их пройти и просмотреть все файлы,
содержащиеся в них. Мы можем сделать это с помощью команды

$ thead $HOME

Если мы хотим просмотреть только исходные файлы на языке Си
(*.c), то представленный выше синтаксис не годится для этого. Он не
обладает достаточной гибкостью. Нам необходимо иметь способ указать
(или квалифицировать) файлы в $HOME перед тем, как просматривать их.
Так как команда thead может воспринимать полные имена файлов, мы можем
использовать следующую команду:

$ find $HOME -name "*.c" -print | sort | thead

Команда find генерирует список файлов с расширением C, который
сортируется и подается по каналу на вход команде thead.
Как видно из представленных двух примеров, весьма полезной для
командного файла является возможность получать входные данные либо из
аргументов командной строки (как в первом примере), либо по программ-
ному каналу (как во втором примере). Способность использовать прог-
раммный канал позволяет вам применять какие-либо другие команды систе-
мы UNIX, которые могут отбирать входные данные для вашего командного
файла. Команда с такой двойной возможностью называется ФИЛЬТРОМ. Среди
стандартных команд системы UNIX вы найдете лишь несколько команд-филь-
тров, таких как wc, awk, sort.
Эти два способа поступления входных данных в программы делают ин-
терфейс с командными файлами очень гибким. Мы можем подстраивать прог-
рамные средства под наши нужды, а не подстраивать наши желания под
имеющееся программное обеспечение.
Аргументами для команды thead являются каталоги. Никаких опций,
начинающихся со знака "-" нет, только каталог или полные имена файлов.
Команда thead знает из синтаксиса, какой способ запуска команды будет
использоваться. Если командная строка содержит имя файла, thead
просмотрит все позиционные параметры. Если никакие имена не указаны,
thead читает стандартный ввод (stdin) и останавливается, когда встре-
чает EOF. (Такое бывает в случае, когда команда thead получает входные
из программного канала.)
Для каждого файла, с которым работает thead, выполняется контроль
- текстовый ли это файл. Применение команды head к исполняемым модулям
приводит к выводу "таинственных" символов на экран и иногда может выз-
вать дамп оперативной памяти.

    ПРИМЕРЫ



1. $ thead /etc

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

2. $ thead /usr/include

Просматривает все подключаемые файлы (*.h), даже в системном под-
каталоге sys.

3. $ find $HOME -ctime 0 -print | thead

Ищет все файлы в вашем регистрационном каталоге, которые были из-
менены в течении последних 24 часов. Для каждого файла проверяется,
текстовый ли он. Если файл текстовый, то он печатается.

    ПОЯСНЕНИЯ



Строки 4-8 выполняют проверку ошибок. Так как команда thead не
имеет никаких опций, любые позиционные параметры, которые начинаются с
дефиса (-) являются неверными. Если первым символом первого позицион-
ного параметра оказывается "-", то печатается сообщение "argument
error" (ошибка аргумента) вместе с сообщением о способе запуска и ко-
манда thead прекращает работу.
Некоторые приемы программирования для интерпретатора shell,
используемые в этих строках, довольно часто встречаются в данной кни-
ге, поэтому имеет смысл остановиться на них подробнее.
Проанализируем строку 4, работающую изнутри наружу. Команда echo
выдает содержимое $1 (текущий параметр командной строки), которое пе-
редается по программному каналу команде cut. Команда cut используется
для того, чтобы выделить определенные символы или группы символов из
строки. В данном случае опция -c1 используется для получения только
первого символа.

КОМАНДА cut ДЛЯ BSD

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

for NAME in 'who | sed "s/^\([^ ]*\).*/\1/"'
do
done

Для каждой обнаруженной строки (аргумента) команда sed должна
подставить вторую строку символов вместо первой строки. Первая строка
- это строка, которая вырезается. Мы ищем от начала строки (^) символ,
отличный от пробела ([^ ]), за которым следует любое число непустых
символов (*). Эта операция прерывается по достижении пробела. Набор
непустых символов ограничивается обратными косыми чертами \( и \).
Впоследствии ссылка на этот набор дается в виде \1. Символы .* означа-
ют, что после того, как найден пробел, необходимо считать подходящими
все символы до конца строки. Мы находимся фактически сразу после того,
что заключено в пару символов \( и \). Группируя первый набор симво-
лов, отличных от пробела, мы получаем то, что является результатом ра-
боты команды "cut -f1".
В этом месте мы подходим к знакам ударения (`), окаймляющим все
выражение. Они берут результат работы всех команд, заключенных в знаки
ударения и передают на следующую охватывающую структуру в наших вло-
женных выражениях. Этот следующий уровень окаймления указан кавычками.
Кавычки превращают символ в строку, чтобы его можно было сравнить с
символом "-". Следующий слой - квадратные скобки, указывающие условие
для оператора if. Это приводит к тому, что генерируется нулевое (исти-
на) или ненулевое (ложь) условие, которое управляет тем, будет ли вы-
полнена часть then оператора if-then.
Мы не собираемся подробно анализировать много строк данного ко-
мандного файла, но мы хотим показать вам, как читать выражение или всю
строку текста программы так, чтобы это имело смысл.
Остальная часть командного файла представляет собой один огромный
оператор выбора (case). Аргументом, используемым для ветвления, явля-
ется число позиционных параметров в командной строке. Если позиционных
параметров нет, то в строках 11-19 активируется цикл while. Заметим,
что цикл while выполняет оператор чтения, но не указывает, откуда дол-
жен быть взят его вход. Это связано с тем, что входом по умолчанию яв-
ляется стандартный ввод (stdin). Для каждого имени файла, которое чи-
тается из стандартного ввода, запускается команда file системы UNIX.
Выход команды file передается по программному каналу команде fgrep (а
не grep, что увеличивает скорость), чтобы посмотреть, является ли файл
текстовым.
Фактический выход команды fgrep перенаправляется на нулевое уст-
ройство (в бесконечную область памяти), поскольку он нам не нужен.
Нас интересует лишь код возврата после выполнения всего конвейе-
ра. Если команды file и fgrep отработали успешно, кодом возврата явля-
ется ноль. Это истинное значение, поэтому выполняется участок цикла
после then (строки 14-17). Если файл не существует или не является
текстовым, то код возврата ненулевой, и условный оператор завершается.
Это приводит нас в конец цикла, выполняется следующая итерация цикла
while и мы рассматриваем следующий аргумент из стандартного ввода.
Теперь рассмотрим обработку, выполняемую по then (строки 14-17).
Для каждого файла, который является текстовым, печатается строка двое-
точий (:) до и после имени файла, а команда head системы UNIX печатает
первые 15 строк. Такой сценарий продолжается, пока не закончатся дан-
ные в стандартном вводе.
Рассмотрим другую альтернативу, покрываемую данным оператором вы-
бора. Она обрабатывает ситуацию, когда имеется несколько позиционных
параметров (что указано символом * в операторе case). Цикл for пробе-
гает все параметры (строка 20). Звездочка (*) в операторе case означа-
ет, что подходит любое значение, которое не подошло ранее. Это улавли-
вающая (catchall) опция. Цикл for использует аргумент $* в качестве
своего входа. Он представляет значения всех позиционных параметров,
что является фактически всей командной строкой, исключая имя утилиты.
Команда find используется для поиска всех нормальных файлов в ка-
талоге. "Нормальные" файлы не означает "только текстовые файлы", поэ-
тому мы проверим это позже. Выход команды find передается по каналу
команде sort, чтобы сделать его более наглядным. Отсортированный
список передается по каналу в цикл while, который помещает имя файла в
переменную FILE (строка 27). Проверяется, текстовый ли файл, затем он
печатается командой head.
Если мы сравним строки 13-18 и строки 24-29, то мы увидим, что
это один и тот же код. В большинстве языков программирования это озна-
чало бы, что мы должны оформить эти строки как процедуру и вызывать
ее, когда нужно. Язык программирования интерпретатора shell, хотя и
довольно мощный, не имеет хорошего способа реализации процедур.
Последний интерпретатор shell в System V имеет функции, которые позво-
ляют решить эти проблемы.
Отметим, что внутренний цикл while повторяется на каждом файле,
который существует в определенном каталоге, а внешний цикл for прохо-
дит от каталога к каталогу.

    ВОЗМОЖНЫЕ МОДИФИКАЦИИ



Для увеличения гибкости хорошо бы добавить опции, чтобы вы могли
переходить на команду find непосредственно из thead. Полезными аргу-
ментами были бы -name для изолирования образцов имен файлов и -ctime
для обработки изменений, связанных со временем.
Еще одной привлекательной особенностью было бы добавление опции
грамматического разбора (основанной на -) и опции -n, указывающей, что
из команды head должно быть напечатано n строк.

    ВОЗМОЖНЫЕ ИССЛЕДОВАНИЯ



В чем отличие между двумя следующими операторами?

$ find $HOME -name "*.c" -print | thead

и

$ find $HOME -name "*.c" -exec head {} \;

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

2.1.3. tgrep - поиск строк в дереве файловой системы

--------------------------------------------------------------
ИМЯ: tgrep
--------------------------------------------------------------

tgrep Поиск строки по шаблону в дереве файлов

    НАЗНАЧЕНИЕ



Обходит файловое дерево и ищет в каждом файле указанную строку.
Если не указан никакой каталог, tgrep действует как фильтр.

    ФОРМАТ ВЫЗОВА



tgrep [-c|-h] string [file ...]

    ПРИМЕР ВЫЗОВА



# tgrep "profanity" /

Поиск слова "profanity" по всей системе (суперпользователь снова
на тропе войны!)

    ТЕКСТ ПРОГРАММЫ



1 :
2 # @(#) tgrep v1.0 Search for string in tree Author: Russ Sage
2а Поиск строки в дереве

4 OPT=""

6 for ARG in $@
7 do
8 if [ "`echo $ARG|cut -c1`" = "-" ]
9 then case $ARG in
10 -c) OPT="-name \"*.c\""
11 shift;;
12 -h) OPT="-name \"*.h\""
13 shift;;
14 *) echo "$O: incorrect argument" >&2
15 echo "usage: $O [-c|-h] string [file ...] >&2
16 exit 1;;
17 esac
18 fi
19 done

21 case $# in
22 0) echo "$O: argument error" >&2
23 echo "usage: $O [-c|-h] string [dir ...]" >&2
24 exit 2
25 ;;
26 1) while read FILE
27 do
28 grep -y "$1" $FILE /dev/nul
29 done
30 ;;
31 *) STRING=$1; shift
32 eval find "$@" -type f $OPT -print | sort | while read FILE
33 do
34 grep -y "$STRING" $FILE /dev/null
35 done
36 ;;
37 esac

    ПЕРЕМЕННЫЕ СРЕДЫ ВЫПОЛНЕНИЯ



FILE Содержит имя каждого файла
OPT Содержит специальные опции команды find
STRING Временная переменная, в которой содержится строка
поиска

ОПИСАНИЕ

ЗАЧЕМ НАМ НУЖЕН КОМАНДНЫЙ ФАЙЛ tgrep?

Как мы могли видеть на примере двух предыдущих утилит, рекурсив-
ный просмотр файлов очень полезен. Он сохраняет время, поскольку поз-
воляет избежать поиска файлов вручную, а также создает средства, кото-
рые могут быть использованы в более мощных утилитах. Чем больше име-
ется созданных нами средств, тем больше новых средств мы можем постро-
ить с их помощью. Единственная проблема заключается в том, что вы
должны позаботиться об их взаимозависимости (каким утилитам или
средствам требуются другие утилиты или средства и кто на кого влияет).
Еще одна область, где UNIX не имеет "родной" рекурсивной команды
- это обработка строк. Семейство команд типа grep очень велико, но все
они работают только по одному фиксированному маршрутному имени файла.
Нам необходим препроцессор для команды grep. Правда, мы можем дать
запрос на все файлы во всей системе или какой-либо ее части по нашему
выбору. Если мы попытаемся сделать это вручную, то это означает, что
мы должны много раз нажимать на клавиши, что может привести к син-
таксической ошибке. Вы также должны точно помнить, как вы создавали
командную строку, если вы в следующий раз захотите выполнить такую же
задачу. Зачем выполнять грязную работу? Для этого существует компь-
ютер.
Создавая программу автоматического обхода дерева файлов, мы осво-
бождаемся для того, чтобы направить нашу энергию на более важные вещи
вместо того, чтобы выпутываться из ситуации в случае какого-либо слиш-
ком специфичного синтаксиса. Один раз создав достаточно мощные
средства доступа к файлам, мы можем посвятить наше время написанию
программ, обрабатывающих файлы данных для решения каких-либо задач.

ЧТО ДЕЛАЕТ tgrep?

Основным предназначением tgrep является обеспечение большей гиб-
кости и легкости использования возможностей команды grep. Ее синтаксис
точно такой же, как и у grep, за исключением допустимых типов файлов.
В команде grep UNIX в качестве аргумента может указываться практически
любой файл, но указание текстового файла имеет наибольший смысл. В ко-
манде tgrep также могут использоваться текстовые файлы, но наибольший
смысл имеет указание каталогов, поскольку мы ищем имена файлов. Коман-
да find работала бы не очень хорошо, если бы пыталась извлечь множест-
во имен файлов из текстового файла. В командной строке может указы-
ваться множество имен каталогов, поскольку все они используются как
начальное место поиска оператора find.
По умолчанию tgrep находит все обычные файлы. В этой программе
нет никакой проверки на то, текстовый файл или нет, поскольку мы не
пытаемся напечатать все на экран. Поэтому мы ищем строки символов во
всех файлах, начиная от архивных и заканчивая исполняемыми.
Если вы хотите выбрать типы файлов, используйте две опции, -c и
-h. Опция -c заставляет команду UNIX find искать только файлы с имена-
ми вида *.c. Аналогично, опция -h соответствует файлам *.h. Эти опции
могут быть полезны для управления программами на языке Си, с которыми
мы более детально познакомимся в главе 4. Эти опции не самое важное,
но они показывают, как легко добавить новые опции в программу.
Если при вызове была указана какая-то иная опция, кроме упомяну-
тых, выводится сообщение об ошибке и программа останавливается. Подоб-
но thead, tgrep является фильтром.

    ПРИМЕРЫ



1. $ tgrep unix $HOME

Поиск любого вхождения слова unix во всех файлах моего регистра-
ционного каталога.

2. $ tgrep -c "^sleep()$" $HOME/src

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

3. # find /usr/src -name "*.c" -print | tgrep "ioctl"

Поиск всех вызовов ioctl в исходных Си-файлах, начиная с каталога
/usr/src. (Обратите внимание, что я являюсь суперпользователем. Это
видно из того, что я занимаюсь поиском в ограниченной части системы, а
именно в исходных дистрибутивах, а также из того, что в качестве сим-
вола приглашения используется символ "#".)

4. $ tgrep "| more" `find . -type f -print`

Поиск символа вертикальной черты (|), после которого следует сло-
во more, в списке имен файлов, генерируемом оператором find. Find пе-
чатает имена всех файлов текущего каталога и всех подкаталогов, кото-
рые являются обычными файлами.

5. $ tgrep trap /bin /usr/bin /etc

Поиск команды прерывания (trap) во всех командных файлах интерп-
ретатора shell, которые имеются в трех каталогах.

    ПОЯСНЕНИЯ



В строке 4 переменная OPT, в которой хранятся необязательные ко-
манды оператора find, инициализируется в нулевое значение.
Строки 6-18 выполняют проверку на наличие ошибок. Проверяется,
является ли первым символом каждого позиционного параметра символ "-".
Если проверка успешна, то проверяется на корректность сам аргумент.
Возможными опциями являются -c и -h. Если указано что-либо другое, вы-
водится сообщение об ошибке и программа завершается. Обратите внима-
ние, что с помощью команды shift допустимые опции удаляются из команд-
ной строки. Это сделано для того, чтобы впоследствии выражение $@ мог-
ло быть использовано для получения только аргументов строки поиска и
маршрута. Выражение $@ является другой формой выражения $ *, в которой
оно распространяется на все позиционные параметры. Однако в последую-
щем тексте мы увидим одно большое отличие между ними.
Еще один трюк сделан при присвоении значения переменной OPT в