ие данных со стандартного ввода. Таким образом, m может быть использована в ка- честве "перехватчика" или как фильтр, как и команда more. Для тех, кто не слишком знаком с опциями команды more, отметим, что существуют две изящные возможности: 1) вход в редактор vi в том месте, где находится курсор при выводе командой more; 2) выход из more для запуска команды shell и возврат в то место, откуда вы вышли. Пер- вая опция выполняется при нажатии клавиши "v" в строке состояния ко- манды more. (То есть когда more отобразила полный экран текста и ждет продолжения.) Вторая опция запускается при вводе ":!cmd" или "!cmd". Когда команда выполнится, more вернется в то же место. Как видите, это синтаксис командной строки ex. Команда more в самом деле имеет неболь- шую часть редактора ex, спрятанную внутри нее. Вы можете выполнить многие команды редактора, указывая их после подсказки в строке состоя- ния команды more. Обычный сеанс работы выглядит так: -------------------------- | | m `path termcap` <-поиск таблицы описания тер- | минала (termcap) и вывод | . ее командой more . . --More--(5%) <-строка состояния more v vi /etc/termcap vi +210 /etc/termcap <-командная строка для редак- тора vi получена от more . . :q <-выход из vi --More--(5%) <-возврат в more :!sh порождение нового shell'а $ date запуск команды date Wed Apr 23 07:15:04 PST 1986 $ ^d <-убрать порожденный shell --More--(5%) <-возврат в more :f распечатка имени файла, выводимого командой more "/etc/termcap" line 54 выход команды f --More--(5%) f <-команда more для пропуска полного экрана .skipping 23 lines . . --More--(9%) <-пропуск и выдача текста q выход из команды more ПРИМЕРЫ 1. $ ll -R / | m Начиная с корневого каталога (/), вывести в длинном формате (ll) все файлы (опция -a подразумевается в ll) всей системы (-R) и постра- нично распечатать на экран (| m). 2. $ m `path inittab rc passwd` Обнаружить и вывести с помощью more системные файлы inittab, rc и passwd. Неприятность здесь заключается в том, что данный маршрут ско- рее всего относится к каталогу /bin/passwd, а не /etc/passwd (посколь- ку каталог /etc размещается в конце каталогов), а это означает, что вы можете попытаться вывести на экран исполняемый файл. В зависимости от того, какую из версий команды more вы запустили, это может привести к чему угодно начиная с сообщения команды more о том, что это был не текстовый файл, и заканчивая тем, что ваш терминал начнет показывать непонятные символы и даже зависнет. ПОЯСНЕНИЯ Поскольку в этом командном файле не так много текста, то все до- вольно понятно, нет ни обработки ошибок, ни других дополнений. Просто нехитрый вызов команды more. Полное имя здесь указано с целью повыше- ния быстродействия, как мы обсуждали ранее. Вы должны перепроверить местонахождение вашей команды more. В системе Berkeley она может нахо- диться в каталоге /usr/ ucb/more. Воспользуйтесь командой path more для определения этого места и вставьте соответствующий маршрут вместо указанного нами. Кстати, фокус попадания этой символьной строки в текст вашего ко- мандного файла состоит в том, чтобы войти в редактор и вызвать следую- щую команду: :.!path more Здесь происходит переход в shell и запуск команды path (:!), за- тем выход команды path (который представляет собой полное маршрутное имя) помещается в буфер редактора в самом начале текущей строки (.). После этого вы имеете эти данные в вашем редактируемом файле и при не- обходимости можете отредактировать их. 2.2.5. mmm - обработка программой nroff макрокоманд для рукописей -------------------------------------------------------------- ИМЯ: mmm -------------------------------------------------------------- mmm Командная строка nroff для макросов обработки рукописей НАЗНАЧЕНИЕ Вызывает текстовый процессор nroff со специальными опциями, кото- рые инициализируют макросы обработки рукописей. ФОРМАТ ВЫЗОВА mmm file [...] ПРИМЕР ВЫЗОВА mmm memo Обработать с помощью nroff файл моих заметок memo и отобразить его на экран ТЕКСТ ПРОГРАММЫ 1 : 2 # @(#) mmm v1.0 Nroff command line with mm macros Author: Russ Sage 2а Командная строка nroff с макросами mm 4 if [ "$#" -eq 0 ] 5 then echo "mmm: wrong arg count" >&2 6 echo "usage: mmm file [...]" >&2 7 exit 1 8 fi 10 LIST="" 11 for ARG in $* 12 do 13 if [ ! -f $ARG ] 14 then echo "mmm: $ARG is not a regular file" >&2 15 else LIST="$LIST $ARG" 16 fi 17 done 19 nroff -r0O -mm $LIST ПЕРЕМЕННЫЕ СРЕДЫ ВЫПОЛНЕНИЯ ARG Содержит каждый позиционный параметр командной строки LIST Содержит список проверяемых имен файлов ОПИСАНИЕ ЗАЧЕМ НУЖЕН КОМАНДНЫЙ ФАЙЛ mmm? Одним из фактов делового мира является работа с бумагами. Мы про- изводим заметки, письма, контракты, документы, руководства и так да- лее. Если вы знакомы со стилем производства документации в системе UNIX, то ваши текстовые файлы в основном представлены в одном из фор- матов программы nroff. Однако различные программы форматирования текстов служат различ- ным целям. Имеется стандартный nroff и nroffс дополнениями, такими как макросы ms и mm. Для подготовки графической информации и выполне- ния типографских работ разработана программа troff. Система AT&T имеет целую программную среду под названием Writers Workbench, и система Berkeley имеет аналогичные возможности. Большинство наших задач по написанию каких-либо текстов может быть сведено к нескольким стандартным форматам, таким как письма, ру- кописи вообще, страницы руководств и так далее. Не так легко запомнить опции команды nroff (или другой команды), которые следует использовать в данном случае, да мы и не должны делать это. Наша команда mmm служит иллюстрацией программы, которую мы можем запускать всякий раз, когда нам нужен определенный формат. Вы можете создать несколько версий программы, которые удовлетворяют вашим собственным нуждам при написа- нии текстов. Использование заготовленных заранее команд означает, что мы можем делать полезную работу, даже если некоторое время мы не выполняли ра- боту определенного вида. Мы также можем избежать многократных нажатий на клавиши. Мастера UNIX'а периодически уединяются в своих горных убе- жищах, где штудируют справочные руководства в поисках полезных, но доселе незамеченных опций, которые могут быть встроены в программные средства для повседневной работы. Если слишком некритично полагаться на ваш текущий набор инструментальных средств, то можно пропустить по- лезные возможности. ЧТО ДЕЛАЕТ mmm? Командный файл mmm - это интерфейсный процессор для команды nroff. Под словом "интерфейсный" мы подразумеваем, что он обрабатывает вызывающую командную строку и устанавливает все опции для вызова прог- раммы nroff. Некоторые из опций nroff жестко запрограммированы в вызо- ве. Эти опции инициализируют отдельные части программы nroff. Если вы не включаете никакие аргументы, mmm распознает это как ошибку и выводит синтаксическую подсказку. Обратите внимание, что если вы передадите mmm такой аргумент, как -z, то этот аргумент будет рассматриваться как имя файла, а не как подлежащая передаче опция, и это снова вызовет ошибку. Вторая ошибка не является фатальной, в то время как первая фатальна. После обработки всех аргументов программа nroff использует имена файлов в качестве файлов с входными данными. По умолчанию вывод произ- водится в stdout (стандартный вывод). Обычно это экран вашего термина- ла, но вывод может быть переадресован или передан по конвейеру на уст- ройство печати или куда-либо еще. ПРИМЕРЫ 1. $ mmm nroffile | m Запуск команды nroff применительно к файлу nroffile, вывод ре- зультата на экран с передачей по конвейеру команде more. Это полезно при изучении утилиты nroff, проведении экспериментов с различными ко- мандами и наблюдения за соответствующими результатами. 2. $ for F in proj.? do mmm $F > $F.rf done Обработка в цикле всех файлов, имена которых содержат символьную строку "proj.", за которой следует один символ. Это могут быть proj.1, proj.2 и так далее по всему набору символов вплоть до proj.z, proj.{, proj.|, proj.} и proj.~, если считать, что у вас есть файлы, имена ко- торых содержат эти символы. Каждый файл обрабатывается, и выход nroff перенаправляется в файл с таким же именем, дополненным символами .rf. 3. $ mmm status[12] | lpr -o5 Обработка командой nroff файлов status1 и status2. Выход в стан- дартный вывод передается по конвейеру программе lpr. Программа lpr яв- ляется фильтром и принимает или имена файлов в командной строке, или непосредственно данные, передаваемые ей по конвейеру (но не то и дру- гое сразу). Опция -o5 указывает lpr сместить страницу на 5 символов. ПОЯСНЕНИЯ В строке 4 проверяется, равно ли нулю количество аргументов в ко- мандной строке. Если да, в стандартный файл ошибок выдается сообщение об ошибке. Выводится также синтаксическая подсказка, и mmm завершается с плохим статусом. Переменная LIST инициализируется нулевым значением в строке 10. Обычно переменные интерпретатора shell и так в начале равны нулю, но предварительная установка значения является хорошим стилем программи- рования. Затем мы обрабатываем каждый аргумент командной строки в цикле (строки 11-17). Все аргументы должны быть именами файлов, поэтому каж- дый из них проверяется на то, существует ли он как обычный файл. Если это не файл, то в стандартный файл ошибок выводится сообщение об ошиб- ке. Тем не менее программа не завершается. Не следует аварийно прекра- щать всю программу только потому, что нет указанного файла. Мы про- пускаем его и идем до конца списка аргументов. Это особенно актуально, если данная команда используется как фоновая во время выполнения дру- гой работы. Пользователь скорее согласится с тем, чтобы было выполнено побольше работы, чем не сделано вообще ничего. Это решение, принятое в данной программе, и вы можете изменить его, если оно не подходит в ва- шей ситуации. Если имени соответствует допустимый файл, оно добавляется в список хороших имен файлов. Этот список становится главным списком для команды nroff. После того как все аргументы проверены, мы в строке 9 строим и выполняем командную строку nroff. Опция -rO0 для nroff указывает макросам обработки рукописей (па- кету mm) установить регистр, который имеет дело с отступом текста, в состояние, соответствующее отступу в 0 символов. Это значит, что весь текст начинается с крайней левой позиции, т.е. выровнен слева. Путем проведения экспериментов я обнаружил, что левое выравнивание текста программой nroff и установка отступа для принтера дает наиболее надеж- ный вывод на печать. В противном случае, если вы установите отступ текста в nroff и отступ в принтере, то может произойти настоящее столк- новение, когда дело коснется вывода колонок в странице. Вы можете из- менить это место, если ваши программы вывода или устройства печати ве- дут себя как-то иначе. Опция -mm указывает программе nroff просмотреть библиотеку макросов обработки рукописей, чтобы определить, использу- ются ли какие-либо из них во входном документе. Эти макросы очень большие и требуют много времени центрального процессора. Если вам не- обходимо использовать их, то вам потребуется большой компьютер или компьютер, специально предназначенный для этой цели, чтобы добиться хорошего времени получения результата. Последним аргументом является $LIST. В этой переменной находится строка имен файлов, разделенных пробелами. Эти имена помещаются в ко- мандную строку nroff. Можете быть уверенными, что в этом месте нет ни- каких ошибок. ВОЗМОЖНЫЕ МОДИФИКАЦИИ Поскольку все аргументы рассматриваются как имена файлов, то у нас нет способа передачи дополнительных команд пакету mm. Наличие та- кой возможности было бы желательным, поскольку при экспериментировании с командой nroff вам необходимо пробовать различные опции, чтобы уви- деть, как они действуют. Было бы тяжелой работой выполнять редактиро- вание текста mmm, чтобы добавить одноразовые опции, которые могут вам никогда не понадобиться или опции, которые вы должны постоянно менять. Один из путей достижения большей гибкости - посмотреть, имеет ли какой-либо аргумент дефис в качестве первого символа. Если да, перех- ватить эту опцию и убрать ее из списка имен файлов. После этого вы бы имели список опций, которые нужно включить в командную строку, и список имен файлов, подлежащих обработке. Отметим, что место, занятое в нашем командном файле указанием па- кета mm, можно вместо этого заполнить ссылкой на другие макропакеты, имеющиеся в вашей системе, например -ms или -me, в зависимости от нуж- ного вам формата. Отказ от поиска макросов, которые вам не нужны, ускорит обработку: подробности вы найдете в документации по nroff или troff. 2.2.6. pall - печать всех файлов в дереве ------------------------------------------------------------- ИМЯ: pall -------------------------------------------------------------- pall Распечатка всех файлов в дереве каталогов НАЗНАЧЕНИЕ Находит все файлы в заданном каталоге в соответствии с некоторым критерием, разбивает файлы на страницы и помещает результат в один файл, готовый к распечатке на принтере. ФОРМАТ ВЫЗОВА pall [-t|-d] directory ПРИМЕР ВЫЗОВА pall /usr/lib Выводит на печать постранично все текстовые файлы в каталоге /usr/lib ТЕКСТ ПРОГРАММЫ 1. : 2 # @(#) pall v1.0 Print all files in a tree Author: Russ Sage 2а Печатает все файлы в дереве 4 if [ $# -eq 0 -o $# -gt 2 ] 5 then echo "pall: wrong argument count" >&2 6 echo "usage: pall [-t|-d] dir" >&2 7 echo " -t text (default)" >&2 8 echo " -d dev (.c,.h,.mk,.s)" >&2 9 exit 1 10 fi 12 NAME="" 13 if [ `echo $1 | cut -c1` = "-" ] 14 then case $1 in 15 -t) NAME="" 16 shift;; 17 -d) NAME="-name \"*.[chms]*\"" 18 shift;; 19 *) echo "pall: invalid arg $1" >&2 20 echo "usage: pall [-t|-d] dir" >&2 21 echo " -t text (default)" >&2 22 echo " -d dev (.c,.h,.mk,.s)" >&2 23 exit 1;; 24 esac 25 fi 27 echo "creating output file: /tmp/lpr$$" 29 eval find $1 -type f $NAME -print | sort | while read FILE 30 do 31 if file $FILE | 32 egrep 'exec|data|empty|reloc|cannot open' >/dev/null 2>&1 33 then continue 34 else file $FILE > /dev/tty 35 pr $FILE 36 fi 37 done >> /tmp/lpr$$ 39 echo "\nSend /tmp/lpr$$ to line printer (y/n): \c" 40 read CMD 41 if [ "$CMD" = "y" ] 42 then lpr /tmp/lpr$$ 43 fi ПЕРЕМЕННЫЕ СРЕДЫ ВЫПОЛНЕНИЯ FILE Содержит имя каждого файла, который должен быть обработан в цикле while NAME Содержит строку поиска для определения местона- хождения указанных файлов CMD Содержит команду выдачи результатов на принтер ОПИСАНИЕ ЗАЧЕМ НУЖЕН КОМАНДНЫЙ ФАЙЛ pall? Эта утилита объединяет концепции обхода дерева файлов и вывода содержимого файлов. Даже когда файлы упрятаны в подкаталогах, мы все равно хотим найти их. Нам необходима для этого утилита, которая обхо- дит древовидную структуру файлов, находит файлы нужного нам типа, го- товит их к распечатке и ставит в очередь для вывода на принтер. Такого рода утилита особенно полезна, если исходные тексты или файлы с документацией хранятся в иерархическом дереве. Дело осложня- ется тем, что обычно эти текстовые файлы смешаны с исполняемыми файла- ми (откомпилированными программами), файлами данных и, возможно, с ар- хивными файлами. Необходимо иметь возможность отфильтровать все непри- годные для печати файлы и подготовить текстовые файлы. Должны быть проверены все файлы с тем, чтобы ни один не был пропущен. Для выполнения всего этого процесса вручную требуется, чтобы вы по команде cd переходили в каждый уровень дерева файлов, находили текстовые файлы, обрабатывали их (обычно командой pr системы UNIX или каким-либо другим текстовым процессором) и распечатывали их. После вы- полнения всей этой работы вы еще должны собрать все отдельные распе- чатки вместе в строго определенном порядке. Это большая работа, под- верженная ошибкам со стороны человека. Почему бы не позволить машине выполнять эту работу? Сейчас мы имеем концепции и средства, необходи- мые для создания такой утилиты. В дополнение к возможности управления файлами, pall также может управлять устройством печати. Обычно каждое задание, поставленное в очередь на выполнение к принтеру, имеет заголовок, который печатается первым. Это значит, что если вы поставили в очередь на печать десять отдельных заданий, то впереди каждого из них будет две-три страницы, которые должны быть убраны вручную. Помножьте это на сотни файлов, и вы будете иметь кучу бумаг, которые должны быть выброшены. Pall исключает эти потери, поскольку все обработанные данные со- бираются в один большой текстовый файл. Когда вся обработка выполнена, этот один файл может быть поставлен в очередь на печать или сохранен для некоторых других целей. Единственное ограничение при таком подходе заключается в максимальном размере файла, который вы можете создать. Этот размер вычисляется умножением значения ulimit на размер блока. Например, мое значение ulimit равно 4096. Размер блока в данном случае равен 512, а не 1024. Максимальный размер файла равен 2097152. Вы мо- жете вычислить это прямо с клавиатуры, как показано ниже: $ ulimit 4096 $ expr 4096 \* 512 2097152 Этого значения достаточно для большинства случаев. ЧТО ДЕЛАЕТ pall? Командный файл pall предназначен для поиска указанных файлов, об- работки их командой UNIX pr и сборки всех результатов в один файл. После того как все исходные файлы будут обработаны командой pr, вам будет задан вопрос о том, хотите ли вы поставить выводной файл в оче- редь на печать к принтеру. Результирующий файл сохраняется в каталоге /tmp, где его можно использовать для других целей или удалить. Опциями pall являются -t и -d. Опция -t используется по умолчанию и нет необходимости ее указывать. Она предназначена для документации и указана в командной строке, чтобы более ясно показать действие, кото- рое будет выполнено. Если выбрана текстовая опция, ищутся все файлы в древовидной структуре и затем отбираются только текстовые файлы. Если указана оп- ция разработки -d (development), то ищутся только файлы, связанные с разработкой программ. Затем эти файлы отфильтровываются с целью полу- чения текстовых файлов. Считается, что к разработке программ относятся файлы, имена которых имеют вид *.c для исходных файлов на языке Си, *.h для включаемых файлов заголовков, *.mk для файлов построения прог- рамм (makefiles) и *.s для исходных файлов на ассемблере. Если требу- ются какие-либо другие шаблоны, то такие символы могут быть легко по- мещены в текст программы. Прежде чем начнет выполняться поиск файлов, на экран выводится имя временного файла, чтобы вы знали, как обратиться к нему после за- вершения выполнения команды. Все результаты, полученные после обработ- ки файлов, направляются в этот один файл. Командный файл pall также выводит на экран сообщения, когда он обрабатывает файлы. Вывод файлов выполняется в реальном времени по мере обработки файлов. Распечатка производится при помощи обычной команды UNIX'а file. По распечатке вы можете судить о том, файлы какого типа обрабатываются в данный момент. Если какой-либо норовистый файл проскользнет, то вы знаете, где он размещен и какого он типа. Это делает отладку гораздо более простой. Для файлов выполняется обработка, которая является действием по умолчанию команды pr. Она разбивает файл на страницы и ставит заголо- вок в начале каждой страницы. Заголовок содержит дату, имя файла и но- мер страницы. Нет никакого иного способа передать заголовок командному файлу pall во время его работы, поскольку он предполагает, что вы хо- тите знать имя каждого файла таким, как оно есть на диске. Изменение строки заголовка вызвало бы только неприятности и дополнительную рабо- ту. Способ вызова pall влияет на формат имени файла в заголовке. Если вы вызвали pall, используя абсолютное имя каталога, то в распечатке используются полные маршрутные имена. Если вы вызвали pall с относи- тельными маршрутными именами, то они и используются при выводе на пе- чать. Внутри pall используется команда find системы UNIX. Команда find использует данные из командной строки, т.е. те, которые ввел пользова- тель. Выводимый заголовок изменяется в зависимости от того, что указа- но в командной строке, которую использует find. Если вы вызываете pall, используя следующую командную строку, то заголовок содержит пол- ное маршрутное имя: ------------------------------------------- | | $ pall /usr/include | | May 5 10:39 1986 /usr/include/a.out.h Page 1 | . | . | . | May 5 10:39 1986 /usr/include/ar.h Page 1 | . | . | . Если вы вызываете pall с помощью относительной нотации, то имена файлов также являются относительными, что не очень хорошо. Если у вас есть несколько каталогов, в которых имеются одинаковые имена файлов, то вы не сможете быть уверены, что смотрите на правильную распечатку. Вот как это может выглядеть: --------------------- | | $ cd /usr/include | $ pall . | | May 5 10:39 1986 ./a.out.h Page 1 | . | . | . May 5 10:39 1986 ./ar.h Page 1 . . . ПРИМЕРЫ 1. $ pall /usr/include Выводит ВСЕ файлы заголовков. Сюда включаются файлы заголовков в подкаталоге sys и во всех других каталогах, которые могут распола- гаться ниже каталога /usr/include. Это и есть причина, по которой был написан командный файл pall. Он создает один огромный листинг всех файлов заголовков в отсортированном порядке с печатью в заголовке страниц полного имени. 2. $ pall $HOME/src Обходит все каталоги, находящиеся ниже каталога исходных текстов, и распечатывает все файлы. ПОЯСНЕНИЯ В самом начале производится проверка на наличие ошибок в команд- ной строке. Если в ней нет аргументов или их больше двух, выводится сообщение об ошибке, синтаксическая подсказка и программа завершается с неудачным статусом возврата. В строке 12 инициализируется переменная NAME. Это действие выпол- няется по умолчанию, поэтому данная строка дает возможность не указы- вать опцию в командной строке. Оператор if в строке 13 означает: "Если первым символом первого аргумента является дефис", то нужно проверить, какая это опция. Если установлена опция -t, то переменная NAME инициализируется нулевым значением, что совпадает с действием по умолчанию, поэтому на самом деле ничего не меняется. Затем эта опция удаляется из командной строки. Если установлена опция -d, то переменная NAME инициализируется для поиска символьной строки, соответствующей именам файлов программ- ной разработки. Обратите внимание, что двойные кавычки внутри операто- ра экранированы, т.е. впереди них стоят символы наклонной черты. Ко- мандный интерпретатор shell воспринимает кавычки вокруг строки поиска на первой фазе синтаксического разбора без отмены присвоения, тем са- мым оставляя двойные кавычки последующей команде find. Если опцией является что-либо другое, выводится сообщение об ошибке и программа завершается. В строке 27 выводится сообщение о том, какой файл содержит ре- зультаты работы. Сам этот оператор не создает файл. Он только печатает имя файла, который будет создан позже. Строки 29-43 - это главный цикл всей программы. Оператор find должен быть повторно проанализирован командой eval, поскольку перемен- ная NAME содержит нужные нам данные. Если бы не было команды eval, то подстановка символьных строк выполнялась бы неправильно. Обратите вни- мание, что переменной NAME не требуются кавычки в строке 24. Они уже есть в переменной NAME, так как были обработаны командой eval. Оператор find находит только файлы типа f, или обычные файлы, т.е. не каталоги и не символьные или блочные устройства. Здесь под "обычными файлами" понимается, что они еще могут быть файлами данных или исполняемыми. Если значение переменной NAME равно нулю, оно не влияет на командную строку. Если NAME содержит символы файлов прог- раммной разработки, то они становятся частью команды find при выполне- нии команды eval. Это накладывает ограничения на шаблон поиска команды find. Когда файлы найдены, их имена выводятся в стандартный вывод. Стандартный вывод по конвейеру передается команде sort, располагающей имена файлов по порядку. Это сильно помогает при сортировке горы вы- водной информации. Чтение кипы распечаток толщиной в один фут может свести с ума кого угодно. Отсортированные имена по конвейеру передаются в цикл while, кото- рый читает имена файлов по одному. Обратите внимание, что стандартный вывод для всего цикла while переадресовывается во временный файл, что облегчает сборку всех выходных результатов в одном месте вместо пере- адресации каждого вызова команды в файл. Для каждого подходящего файла выполняется проверка в строках 31-36. Проверка начинается с запуска команды file. Выход file по кон- вейеру передается команде egrep, которая ищет тип файла, соответствую- щий набору нескольких выражений. Если какое-либо выражение подходит, то нам не нужно обрабатывать этот файл. Это не текстовый файл, и его нельзя вывести на принтер. Во многих случаях файлы данных содержат большое количество символов прогона формата, которые выталкивают стра- ницу после каждой пары символов. Если вы не будете находиться рядом с принтером, когда печатаются такие файлы, то вы можете получить листинг, занимающий половину ящика бумаги, затратив целый лес на не- нужную работу. Нам не нужен выход команды egrep, а только ее статус возврата. Если egrep обнаруживает одно из указанных ей выражений, она заверша- ется со статусом успеха, или 0. Тем самым проверка if включает выпол- нение оператора then, который в данном случае выводит нас из конструк- ции if-then-else и продолжает цикл while, пропуская таким образом файл. Если же egrep не обнаружила ни одну из указанных символьных строк, то выполнение продолжается с оператора else, который выполняет еще одну команду file и переадресовывает ее вывод на устройство с име- нем /dev/tty. Это универсальное имя устройства, которое гарантирует вам вывод на экран вашего терминала. UNIX обеспечивает, что указание /dev/tty обходит любые команды переадресации вывода, действующие в данный момент. Поскольку стандартный вывод уже переадресован для всего цикла while, то нам нужно попасть на устройство /dev/tty, чтобы вывод шел на экран терминала, а не в файл печати. Отображение на терминал имени обрабатываемого файла позволяет пользователю знать, какой файл будет добавлен к распечатке. Если файл удовлетворяет нашим критериям, он обрабатывается коман- дой pr. Результат направляется в стандартный вывод, который переад- ресован циклом while так, чтобы результат четко попадал в один файл. Отметим, что нам нужно поставить символ добавления в файл вывода (>>). В противном случае мы получим запись на место существующего файла пе- чати, а значит в файле печати будет находиться только последний обра- ботанный файл. После того как все файлы обработаны, задается вопрос о том, хоти- те ли вы вывести результирующий файл на печать. Предлагается ответить на этот вопрос "да" (yes) или "нет" (no), однако в программе проверя- ется только положительный ответ (yes). Это значит, что нажатие любой клавиши трактуется как ответ "no", кроме клавиши "y", означающей "да". Ответ пользователя читается с клавиатуры, и проверяется, является ли он символом "y". Если да, то файл ставится в очередь на печать. Если нет, дальнейшая проверка не производится и командный файл завершается. Отметим, что запрос о выводе на печать поступил в стандартный вы- вод. Переадресация вывода действовала только во время работы цикла while, а затем прекратилась. Так было сделано потому, что цикл while был фактически еще одним порожденным shell-процессом (subshell) и пе- реадресация действовала только в этом те внимание, что маршрутная- установите значения переменных вне цикла, а затем измените их внутри цикла. После завершения цикла переменные по-прежнему имеют свои перво- начальные значения, а не измененные в цикле значения. Измененные зна- чения касались переменных порожденного интерпретатора shell, которые исчезли, когда порожденный shell завершился. Переменные интерпретатора shell могут передавать значения только вниз, порожденным процессам, но процессы-потомки не могут передавать значения переменных вверх, роди- тельскому процессу. Обычно передача значений переменных поддерживается при помощи какого-либо файла, в котором хранятся данные для обмена между родительским процессом и процессом-потомком. УПРАВЛЕНИЕ ВЫВОДНЫМИ ФАЙЛАМИ БОЛЬШИХ РАЗМЕРОВ Как мы уже отмечали, общий размер выводного файла ограничен. На- помним, что команда find проходит все дерево каталогов вниз до конца по всем поддеревьям, начиная с каталога, имя которого указано в ко- мандной строке. Если вы находитесь на вершине очень глубокого дерева, то обрабатываться могут буквально сотни файлов. Поскольку вы ограниче- ны максимальным размером выводного файла, вы можете обработать только ограниченное число файлов. Конечно, количество файлов, которое вы мо- жете обработать, зависит также от того, насколько велики входные фай- лы. Если выводной файл достигает своего максимума, все добавляемые после этого данные теряются. Потеря данных весьма болезненна, и обычно требуется некоторое время, чтобы ее обнаружить. В медленно работающей системе попытка обработать большое дерево, например все исходные тексты системы UNIX, может занять целый час и даже больше, прежде чем выходной файл заполнится. Это означает, что вы должны находиться рядом и следить за тем, когда файл переполнится. Если он все-таки перепол- нился, вы должны все выбросить и начать сначала. Это также означает, что вы должны перейти вниз по дереву. Это может быть проблемой в сба- лансированных деревьях. Например, рассмотрим каталог /usr/lib. Этот каталог содержит мно- го файлов на первом уровне и много каталогов первого уровня. Если бы мы не обработали все файлы каталога /usr/lib за одну попытку, мы долж- ны были бы пойти вниз по подкаталогам каталога /usr/lib. Попытки де- лать это вручную и запускать pall в каждом подкаталоге заняли бы много времени и могли бы привести к ошибкам с вашей стороны. Кроме того, pall допускает указание только одного имени каталога, что приведет к получению большого количества распечаток и к путанице при их сортиров- ке. Что же делать? Радикальным решением является увеличение значения ulimit. Вы можете сделать это либо с помощью программы на языке Си, использующей системный вызов ulimit, либо командой shell'а ulimit. Техника выполнения такой работы представлена в главе 7. ВОЗМОЖНЫЕ МОДИФИКАЦИИ Возможно, вы захотите добавить свои собственные штрихи в некото- рых местах командного файла. Первым местом является то, где указыва- ются символы поиска файлов программной разработки. Символы, использо- ванные нами - это наиболее употребимые суффиксы в UNIX. Если вы используете не Си и ассемблер, а другие языки, то вы можете добавить соответствующие символы. Следующим местом, где могут быть сделаны дополнения, являются оп- ции, которые может понимать pall. Вам могут понадобиться файлы с опре- деленными именами или определенными типами, например, файлы nroff. Эти опции могут быть легко добавлены в оператор case, что улучшит команду. Последним местом возможных изменений является тип файлов, которые нужно пропускать. Символьная строка для команды egrep покрывает боль- шинство важных нетекстовых типов файлов. В вашей системе могут быть какие-то особые типы или же имена могут быть другими. Если вам необхо- димо дополнить строку, сделайте это. Команда egrep может обработать довольно много информации. Я не знаю ее ограничений. Возможно, вы об- наружите их, просматривая исходный текст утилиты egrep. Если получа- ется слишком длинная строка и не помещается на экране, ничего страшно- го. Перенос на следующие строки экрана не опасен, пока общее количест- во символов не превысит 255. Опасно только указывать переадресацию символьной строки if на нулевое устройство в следующей после команды egrep строке. Кажется, что все работает правильно, но это не так. Пе- реадресация должна указываться в той же строке, где стоит команда egrep. В данной главе сделано очень много. Наиболее важно то, что полу- чено множество новых идей, которые можно использовать при эксплуатации программной среды и просмотре файлов любого типа. В следующей главе мы углубимся в рутинную работу по ежедневному сопровождению файлов и используем изученные средства, чтобы они облегчили нашу жизнь.  * ГЛАВА 3. Поддержка файловой системы *  СОДЕРЖАНИЕ ВВЕДЕНИЕ 3.1. СОПРОВОЖДЕНИЕ ФАЙЛОВ 3.1.1. Операции сопровождения 3.1.2. Средства пересылки файлов 3.1.3. Средства копирования 3.1.4. Средства проверки операции копирования 3.2. ПЕРЕСЫЛКА ФАЙЛОВ 3.2.1. cptdir - копирование дерева каталога 3.2.2. can - удаление файлов в "мусорную корзину" 3.2.3. dosflp - копирование файлов с гибкого диска формата MS-DOS с использованием символов шаблона в именах файлов 3.3. СРЕДСТВА ПОЛУЧЕНИЯ РЕЗЕРВНЫХ КОПИЙ 3.3.1. autobkp - автоматически наращивамый файл резервной копии 3.3.2. cpiobr - копирование и восстановление файлов в виде потока данных 3.4. СРЕДСТВА ПРОВЕРКИ ОПЕРАЦИЙ КОПИРОВАНИЯ 3.4.1. dsum - контрольные суммы двух катологов 3.4.2. log - меню доступа к файлам протокола копирования ВВЕДЕНИЕ Даже "небольшая" система UNIX с малым числом пользователей порож- дает сотни файлов в ходе обычной работы. В процессе программирования вы можете создавать множество файлов для различных версий ваших программ. Ведение почты и запись текста при помощи редактора vi способствует то- му, что накапливается еще больше файлов. Такие утилиты, как uucp, lp и другие добавляют еще больше файлов. Если у вас система UNIX установлена на микро-ЭВМ, то ваш жесткий диск начинает переполняться. В больших многопользовательских системах дисковая память редко считается пробле- мой, но в действительности всегда кажется, будто файлы стремятся расши- риться до заполнения всей доступной дисковой памяти. Поэтому каждый пользователь должен нести ответственность за расход дискового прост- ранства. (Если вы платите за дисковую память, то у вас также могут быть финансовые стимулы.) Однако, то, что вы хотите сохранить, вы хотите СОХРАНИТЬ. Именно здесь начинается работа по созданию резервных копий. 3.1. СОПРОВОЖДЕНИЕ ФАЙЛОВ В предыдущей главе мы разработали некоторые средства поиска и отображения информации, помогающие нам поддерживать жизненный путь всех наших файлов. Теперь мы собираемся обратиться к важнейшим рутинным ра- ботам, которые позволят избежать хаоса и катастрофы. Сопровождение файлов означает избавление от файлов, которые нам больше не нужны и в то же время систематическое копирование тех файлов, которые мы хотим сохранить. Для этого требуется возможность использова- ния разнородных доступных носителей данных. Сопровождение файлов подра- зумевает также ряд систематических, повторяющихся задач, а это означа- ет, что мы можем создать средства системы UNIX для автоматизации этого процесса. 3.1.1. ОПЕРАЦИИ СОПРОВОЖДЕНИЯ Сопровождение файлов включает два вида операций: создание резерв- ных копий (копирование) и удаление "мусора". Копирование - это дань уважения, которую мы платим за хрупкость физических данных в руки Мерфи и других богов энтропии. Хорошее средство копирования является быстрым, гибким, простым в использовании и стимулирует пользователей часто копировать самые важные файлы. В последующем тексте будут представлены различные методы копирования, пригодные для разных конфигураций системы и типов носителей. Имеется два вида резервных копий: "мягкие" и "твердые". "Мягкие" резервные копии - это копии в другом файле или каталоге в той же или в другой файловой системе (т.е. разделе) на том же или другом жестком диске. Такого рода копирование сделать легко и оно предохраняет от на- носимого самому себе ущерба, такого как удаление файла по невниматель- ности. Чаще всего для такого типа копирования используется наше средство cptdir. Основной недостаток мягкого копирования заключается в том, что вы по-прежнему уязвимы для таких воздействий, которые влияют на ваш физический носитель (обычно жесткий диск) так, что и оригинал и копия оказываются разрушенными. "Твердая" копия - это копия на другом устройстве или даже в другой системе UNIX. Средства, представленные ниже в данной главе, управляют такого рода копированием и дают вам возможность выполнять копирование такого типа и с такой периодичностью, которые соответствуют объему ва- шей вычислительной системы, уровню ее активности и важности хранимых данных. Твердое копирование всегда несколько утомительно, потому что диски или ленты должны быть смонтированы (или должна быть установлена связь с другой системой), а эта операция требует много времени. Преимущество, естественно, заключается в том, что вы больше не зависите от целост- ности какого-либо одного устройства. Автоматизируя нашу процедуру копирования, мы стараемся сделать его как можно менее болезненным. Делая наши средства копирования в какой-то степени разумными, мы можем выбрать только файлы, которые нуждаются в копировании, и тем самым сохранить время и память. Наилучший способ обеспечить, чтобы копирование выполнялось регулярно - минимизировать время и требуемые для этого усилия. Наконец, создание процедур для про- верки правильности копий даст вам спокойствие духа. "Удаление мусора" можно автоматизировать путем указания и подго- товки к удалению файлов, которые, вероятно, будут временными, либо ка- ких-то других файлов, которые созданы (но не обязательно разрушены) при компиляции, выполнении конвейеров или другими операциями. Вы также мо- жете указывать файлы, специфичные для ваших работ как не подлежащие удалению. 3.1.2. СРЕДСТВА ПЕРЕСЫЛКИ ФАЙЛОВ Первая группа средств - это простые универсальные переносчики фай- лов. Программа cptdir может копировать каталог (и любые подчиненные ка- талоги, лежащие ниже в дереве) в каталог-приемник. Каталог-приемник - это обычно каталог, назначенный в качестве резервной копии для некото- рого проекта. Программа can берет на себя