| tee $HBB/board/session$$ Строка 25 присваивает переменной HDIRS все имена каталоговых пе- ременных, что облегчает подключение всех каталогов без повторного вво- да их имен. Мы можем просмотреть все каталоги и напечатать размер используемого дискового пространства: $ for DIR in $HDIRS > do > echo "disk usage for $DIR: `du -s $DIR`" > done Строка 26 экспортирует переменные так, чтобы мы могли всегда их использовать. Отметим, что мы экспортировали $HDIRS и HDIRS. Перед тем, как выполнить экспортирование, $HDIRS было распространено на все различные имена переменных. Следовательно, фактически мы экспортирова- ли все имена плюс саму переменную HDIRS. Строка 28 инициализирует P так, чтобы это был ваш каталог в PUBDIR, то есть /usr/spool/uucppublic. Теперь у нас есть простой способ ссылаться на наши файлы при работе с командой uucp. Строка 30 устанавливает CDPATH. Это путь, который проверяется, когда вы выполняете команду cd. Сначала проверяется текущий каталог (.) на предмет того, есть ли в нем имя каталога, в который вы хотите попасть. Затем проверяется .. (родительский каталог). После этого просматривается ваш регистрационный каталог. Последним назначением CDPATH является $HDIRS, что подключает имена всех подкаталогов. Цель этих имен - позволить команде cd искать в соответствующем каталоге введенное вами имя. Например, если бы вы были в /etc и набрали "cd doc", вы бы попали в $HOME/doc, поскольку CDPATH содержало в себе $HOME. Аналогично, если бы вы имели подкаталог $HOME/doc/status и ввели "cd status" откуда-ли- бо из другого места в системе, вы бы пришли в $HOME/doc/status, так как корень $HOME/doc был в CDPATH. Порядок поиска в каталогах такой же, как объявлено в переменной CDPATH. Если вы вводите имя каталога, которое встречается более чем в одном месте, вы попадаете в первый каталог, обнаруженный при последо- вательном поиске. Например, если бы вы сказали "cd sys", то попали бы в $HOME/sys прежде, чем в $HOME/ src/sys. В табл. 1-1 приведен пример эквивалентных команд cd, представлен- ных в трех различных формах, которые понимает UNIX. То, какую форму вы используете, зависит от того, что считается наиболее удобным и требует как можно меньше нажатий клавиш. Таблица 1-1 Три способа использования команды cd ------------------------------------------------------------- Абсолютный CDPATH Относительно переменной ------------------------------------------------------------- cd /usr/russ cd cd $HOME cd /usr/russ/src/asm cd asm cd $HSR/asm cd /usr/russ/doc/paper/conf cd paper/conf cd $HD/paper/conf cd /usr/russ/tmp cd tmp cd $HT ------------------------------------------------------------- Строка 31 инициализирует переменную PATH. PATH работает таким же образом, как CDPATH. Она ищет программы, которые нужно запустить, в каждом каталоге, указанном в переменной PATH. Если имя не найдено ни в одном из этих каталогов, печатается сообщение ": not found" ("<имя-файла>: не найдено"). Поскольку мы можем установить наш PATH как угодно, можно указать все таинственные места в системе, в которых расположены исполняемые модули. Когда мы хотим их выполнить, мы не обязаны их искать и наби- рать полное маршрутное имя. Чтобы дополнить PATH, введите, например, следующее: PATH=$PATH:/usr/lib/uucp Команда paths, представленная далее в этой книге, использует $PATH, чтобы сообщить нам, в каком каталоге размещен исполняемый мо- дуль. Строка 32 инициализирует переменную SHELL. Эту переменную могут использовать не более чем одна или две утилиты. Обычно она устанавли- вается системой, когда вы регистрируетесь. Строка 33 экспортирует пе- ременные CDPATH, PATH и SHELL. Строки 35-39 - это хитрый способ установки определений термина- лов. Строка 35 начинается со спрятанной команды tty, заключенной в знаки ударения (`...`). Выходом команды tty является "/dev/tty00". За- тем мы берем основное имя этой строки, т.е. "tty00". Далее мы исполь- зуем структуру переключателя по этому значению, чтобы увидеть, что мы хотим сделать для каждого конкретного терминала. Команды tset, пока- занные здесь, относятся к среде XENIX и могут быть неприемлемыми в ва- шей среде. Строка 41 делает эхо-отображение значения TERM на экран, чтобы сообщить вам тип вашего терминала, если он вам нужен. Это значение доступно, если описанная ранее команда tset устанавливает для вас TERM как часть своей обычной работы. В строке 42 устанавливается переменная TERMCAP, указывающая на /etc/termcap. Это обычный способ установки переменной TERMCAP. Другой способ - присвоить TERMCAP текущую закодированную строку, которая на- ходится в файле описания терминала. Если TERMCAP установлен на закоди- рованную строку, то утилите vi нет необходимости обращаться к файлово- му вводу-выводу, чтобы получить характеристики вашего терминала. Стро- ка 43 экспортирует эти значения так, чтобы они были доступны на любом уровне интерпретатора shell. Строка 45 устанавливает частотную переменную. Это переменная из XENIX и, возможно, имеется в System V. Она используется для установки информации о времени. Строка 46 устанавливает информацию о зоне времени, как это требу- ется в библиотечном вызове ctime(3). Имея переменную TZ, вы можете пе- рекрыть подразумеваемую зону времени при доступе ко времени из прог- раммы на языке Си. Строка 47 экспортирует эти переменные. Строка 49 устанавливает ваше значение маски пользователя (umask). Она управляет подразумеваемым разрешением доступа для всех файлов, ко- торые вы создаете. Система вычитает значение umask из 777. Результат становится правом доступа к файлу, в данном случае 755. Когда вы соз- даете каталог с правом доступа 755, этот каталог показывается командой "ls -l" как rwxr-xr-x. Когда вы создаете некаталоговый файл с правом доступа 755, этот файл показывается как rw-r--r--, что эквивалентно 644. Некаталоговые файлы не имеют бита x, поэтому их нельзя исполнить. Каталогам же нужен установленный бит x, чтобы они были доступны по ко- манде cd. Строки 51 и 52 сообщают вам о времени вашего сеанса работы в системе. Строка 51 сообщает вам текущее время вашего входа в систему, а строка 52 вызывает программу lastlog, которая печатает дату вашей последней регистрации в системе. Программа lastlog описана в главе 5. Строки 54-58 инициализируют переменные, генерирующие цвета на цветном мониторе. Управляющие значения являются стандартными значения- ми кодов ANSI. Это работает в системе XENIX и может работать в вашей системе. Растровая графика не доступна, но имеется символьная графика и различные основные (foreground) и фоновые (background) цвета. Основ- ные цвета кодируются числами, начиная с 30, а фоновые цвета - числами с 40. Строки 60-66 - просто для забавы. Они представляют собой хитрый способ устанавливать каждый день на экране различные цвета. Строка 60 начинается с запуска команды date и передачи ее выхода по конвейеру команде cut. Вырезается первое поле, которое является днем недели. За- тем мы создаем структуру переключателя по строке дня, выполняя различ- ные действия для каждого дня. Благодаря эхо-отображению управляющих последовательностей, монитор реагирует немедленно. ТЕОРИЯ ОТНОСИТЕЛЬНОСТИ ВНУТРИ СИСТЕМЫ UNIX Теперь, когда мы ознакомились с "домашней" средой, следующий шаг - обратиться к средам, находящимся вне регистрационного каталога ($HOME). Например, что представляют собой другие каталоги на том же уровне, что ваш $HOME ? Кто еще работает в системе? Как попроще полу- чить доступ к их каталогам? Можете ли вы запускать программы в чужих каталогах? Такого рода вопросы и действия относятся к другим людям в вашей системе. Единственный способ ответить на эти вопросы - посмотреть вокруг себя. Никто не собирается рассказывать вам, что такое система. Вы должны сами исследовать ее и выяснить, куда вы можете ходить, а куда нет. Система конечна, так что вы можете себе помочь, делая распечатки всех каталогов и файлов. Вы можете маневрировать в системе UNIX, используя относительную нотацию. Поскольку системное дерево образовано из каталогов, обозначе- ния . и .. позволяют нам двигаться вверх и вниз по дереву. В любой точке .. означает родительский каталог текущего каталога, в котором мы находимся. Ниже показаны некоторые примеры относительных команд. ls -l $HOME/.. перечисляет файлы в моем родительском каталоге. cd ../../.. в предположении, что текущим каталогом является /usr/russ/src/c, делает моим текущим каталогом /usr. ls . перечисляет файлы в текущем каталоге. ls .. перечисляет файлы в моем родительском каталоге. $HOME/../../bin/ls запускает ls в каталоге /usr/russ/../../bin, т.е. в /bin/ls. ../fred/bin/ls запускает команду ls в каталоге двоичных модулей Фреда, который имеет тот же родительский каталог, что и я, т.е. /usr/fred/bin/ls. ОБЩАЯ СИСТЕМНАЯ СРЕДА Системная среда не просто НАХОДИТСЯ в системе UNIX, а ЯВЛЯЕТСЯ системой UNIX. Как мы увидим в этой книге, вся система - UNIX, Си, ко- манды, файлы и т.д. - это просто логический подход к функционированию компьютера. Программное обеспечение - это то, что определяет система для конечного пользователя. Мы можем представлять все машины, работаю- щие в системе UNIX, как одинаковые и трактовать каждый UNIX как один и тот же. Мы предполагаем, что реакция машины будет каждый раз одинако- вой. Мы можем смотреть на UNIX таким же образом, как на физические за- коны. Мы ограничены ими, но мы также вольны применять эти законы в си- туациях и областях, с которыми мы до этого никогда не встречались. Мы можем доверять этим законам и допускать, что они применимы везде, куда бы мы ни направились. Такова система UNIX, по крайней мере в идеале. Система имеет много сред. Важно понимать, что они собой представ- ляют, как взаимодействуют и для чего могут быть использованы. Так же, как программы = структуры данных + алгоритмы так и UNIX = файловое дерево + утилиты Среда UNIX - это сочетание двух важнейших вещей: файлового дерева и интерфейса системных вызовов. Это дерево допускает бесконечное расширение возможностей, позволяя монтировать внешние дисковые области в любой точке файловой системы. Дерево помогает также в сборе логи- чески связанных файлов, что делает систему более организованной. Интерфейс системных вызовов обеспечивает набор инструментов, из которых можно построить большинство других функций. Определение интер- фейса System V имеется в виде типографской книги и может быть найдено в книжных магазинах. Строгое следование этому стандарту гарантирует совместимость с постоянно развивающейся AT&T System V. ОБЩЕЕ ФАЙЛОВОЕ ДЕРЕВО Для того чтобы лучше понять мир UNIX, посмотрите пример распечат- ки структуры UNIX на рис.1-3 . Это наглядное представление полного де- рева корневой файловой системы. Любые другие расширения файловой системы монтируются на эту файловую систему. Точкой временного монтирования является /mnt. Более постоянные точки монтирования должны быть созданы администратором, например /0, /1 и т.д. или /usr1, /usr2 и т.д. ПЕРВЫЙ СЛОЙ Самым левым каталогом является /bin, который содержит все главные двоичные утилиты. Это наибольший из двух основных каталогов двоичных модулей. Следующий каталог - /dev, в котором размещены все файлы уст- ройств. Файлы устройств являются точками доступа к периферии, подсое- диненной к системе. Этот файл привязан к периферии с помощью ядра и драйвера устройства. Административные утилиты и конфигурационные файлы хранятся в /etc. Примерами являются getty и gettydef, init и inittab, а также файл паролей (/etc/passwd). Следующий каталог - /lib, где размещены библиотеки компилятора. Здесь могут храниться и другие типы библиотек. Каталог /lost+found используется утилитой fsck (главное средство поддержания файловой системы) для хранения логически удаленных файлов. Если на самом деле вы хотите сохранить эти файлы, они могут быть изв- лечены из этой удерживающей области после завершения уборки файловой системы. Следующий каталог - /mnt. Это временная точка монтирования для файловых систем. Мы часто монтируем и демонтируем файловые системы просто для того, чтобы запустить быструю проверку чего-либо. Здесь под- ходящее место для этого. Главным временным рабочим каталогом системы является /tmp. Многие утилиты, такие как vi, fsck, интерпретаторы shell и программы резерв- ного копирования, используют /tmp для хранения рабочих файлов. Следующий каталог - /usr, который применяется как точка монтиро- вания. Файловая система, смонтированная здесь, содержит дополнительную системную информацию и каталоги пользователей. Это разделение между загружаемой файловой системой и пользовательской файловой системой бы- ло сделано, чтобы сбалансировать загрузку диска. Если бы все важные файлы были в одном разделе, он был бы слишком большим. Производитель- ность может быть ухудшена, если все действия направлены в одну логи- ческую область диска. Благодаря разбивке всей системы на две, каждая файловая система поддерживает разумное количество свободного прост- ранства. Чуть ниже мы рассмотрим каталог /usr более подробно. Последний файл - это само ядро, /unix. Весь /unix фактически су- ществует и представляет собой большой a.out (скомпилированный объект- ный файл). Ядро изготавливается путем запуска ld на группе библиотек, которые загружаются по очереди в огромный исполняемый модуль, называе- мый /unix. Машина запускается с первых 512 байтов корневой файловой системы. Программа начальной загрузки, которая находится здесь, загру- жает программу загрузки большего размера, иногда называемую /boot. /boot загружает и запускает /unix. ВТОРОЙ СЛОЙ Второй слой каталогов размещается под /usr. Как упоминалось ра- нее, /usr используется как точка монтирования для другой файловой системы. Это значит, что все файлы, которые имеются в /usr, находятся в другом разделе загружаемого диска или вообще на другом диске. Первым каталогом является adm, для администрирования. Он содержит учетные файлы и регистрационный файл для su (супер- пользователя), а также другие административные файлы. В каталоге bin имеются исполняемые модули, которые используются менее часто, чем модули в двоичном каталоге корневого уровня (/bin). Почти все исполняемые модули распределены между этими двумя каталога- ми. Другие исполняемые модули рассеяны по всей системе, например /usr/lib/uucp/uucico и /usr/lib/ ex3.7preserve. Далее games. UNIX приходит с ассортиментом интересных игр. Боль- шинство из них текстовые, но предоставляется несколько программ графи- ческого типа, например worm, worms и rain. Каталог include содержит все файлы-заголовки. Файлы-заголовки используются в программах на языке Си для определения структур и системных присваиваний, полезных для программирования. Здесь имеется подкаталог sys, который содержит все файлы= заголовки, относящиеся к системе. Читая эти файлы-заголовки, можно многое узнать о системе UNIX. Следующий каталог - lib, который содержит библиотечные файлы для всех видов "имущества": файлы печатающих устройств, файлы поддержки утилиты vi, другие языки и uucp. Каталог /usr/ lib представляется складом всяких библиотек, которые имеются в системе, отличных от биб- лиотек компилятора. Каталог lost+found находится здесь для той же цели, что и однои- менный каталог корневого уровня. Каждая файловая система должна иметь такой файл. Без него fsck не имеет временного места для размещения по- луудаленных файлов и поэтому удаляет их навсегда. В каталоге mail находится ваш системный почтовый ящик. Когда вы запускаете команду mail, здесь накапливается очередь сообщений. В ка- талоге usr/mail каждый файл носит имя пользователя. В этом файле хра- нится почта пользователя, пока он не прочитает ее. Каталог man предназначен для активных страниц руководств по системе UNIX. Наличие постоянного доступа к страницам руководств явля- ется хорошим средством. Однако, эти страницы занимают много места, и доступ к ним может потребовать довольно много времени при сильно заг- руженной системе. В каталоге news хранятся все файлы новостей. Эти файлы именованы в соответствии с порядком, в котором они были введены в каталог. Ко- манда news(1) смотрит на дату файла $HOME/ .news_time, чтобы сообщить, какие новости вы еще не читали. Каталог preserve предназначен для файлов, связанных с утилитой vi. Они помещаются сюда, когда вы работаете с vi или с редактором ex и пропадает питание машины либо ваш сеанс работы прерывается в виде "за- висания". Когда в системе восстанавливается питание, /tmp содержит файлы редактора ex. Из каталога /etc/rc запускается утилита /usr/lib/ex3.7preserve, которая просматривает /tmp, преобразует его в сохраненный файл и помещает его в /usr/preserve. Когда вы входите в систему, вы получаете почту о том, что у вас имеется сохраненный файл редактора, который вы можете восстановить и поместить его на исходное место. Каталог pub не содержит ничего особенного, обычно в нем просто некоторые информационные файлы вроде таблицы ASCII или греческих сим- волов. Каталог spool - это главная точка входа для всех буферизованных файлов в системе. В этом каталоге имеется много подкаталогов, содержа- щих специфические типы буферизованных файлов. Некоторыми типичными подкаталогами являются lp, uucp и uucppublic. В каталоге src хранится исходный код системы UNIX, если он име- ется в системе. От этого каталога ответвляется много уровней: команды, библиотеки, код ядра, код машинного языка и автономные утилиты. Часто в /usr/src хранится также исходный код для локальной машины. Каталог sys традиционно хранит файлы, необходимые для генерации нового ядра. Это файлы-заголовки, конфигурационный файл, библиотеки и командный файл для создания нового ядра из всех этих файлов. Последний каталог - tmp. Это вторичная временная область хране- ния, которая используется не так часто, как /tmp. Ее, однако, исполь- зует утилита sort. ЖИЗНЬ СИСТЕМЫ UNIX: НЕКОТОРЫЕ МЕТАФОРЫ UNIX - это особый мир, живущий своей жизнью. Его социальная структура имитирует реальную жизнь, с правительством, содержащим пра- вителя (корень root), штатом поддержки (bin, cron, lp, sys) и массами (/usr/*). Массы не имеют доступа к мощи правителя, если не используют предварительно установленных средств (/bin/su) или не занимаются кри- минальными действиями и нарушением мер безопасности. Как и в любом об- ществе, большая многопользовательская система UNIX устанавливает права и обязанности своих пользователей. При входе в систему пользователь получает свое "место под солн- цем" (регистрационный каталог - $HOME ). Это место зависит от того, что было раньше (от родительского каталога ..), а будущие места за- висят от того, что происходит позже (каталоги, подчиненные $HOME). Работа распределяется по организациям и иерархиям в зависимости от их функций в обществе (все пользователи в /usr, все транзитные фай- лы в /usr/spool, все функции безопасности в /etc). Посмотрите вокруг себя в вашей системе, чтобы ознакомиться с вашим миром. Вы можете после этого выбрать, участвовать ли в некоторой части этого мира или игнорировать ее. Движение людей в системе UNIX происходит параллельно. Некоторые области (/tmp) доступны всем, а некоторые области сильно охраняются от большинства людей (/etc/passwd). Транспортная служба может перевезти наши вещи (передача файлов по сетям uucp). Мы даже можем воспользо- ваться общественным транспортом, чтобы добраться в разные части города (вход в другие системы (rlogin), эта особенность имеется только в BSD). В мире UNIX нам доступны различные пути. Эти пути помогают нам сформировать свою судьбу (дисковые разделы, монтированные в любое место файлового дерева). Когда дисковый пакет монтируется, он стано- вится доступным нам. Когда он демонтируется, мы теряем доступ к нему. Когда запускаются процессы, они проходят через различные этапы своей жизни. Они рождаются (ответвляются), растут (становятся планиру- емыми и помещаются в таблицу процессов) и, наконец, становятся произ- водительными рабочими в обществе (переходят в состояние запуска и вы- полняются). Все процессы имеют фамильное дерево. Порожденный процесс всегда имеет родителя, а родительские процессы могут порождать много "детей". В зависимости от приложения, они могут быть "дедами" и "внуками". Про- цессы "умирают" так же легко, как создаются. Одной из необычных вещей в мире UNIX является то, что "дети" почти всегда "умирают" раньше сво- их "родителей". Правительство (ядро) проводит в жизнь параметры среды, которые выглядели бы в довольно тоталитарном духе, если бы это было в реальном мире. Только определенное число рабочих допускается к рабочему месту одновременно (это максимальное количество ячеек в таблице процессов). Рабочие ограничены в числе "детей", которых они могут иметь (макси- мальное количество процессов на пользователя). Поскольку рабочие на- капливают материальные ценности, они ограничены в количестве товаров, которые они могут поместить в комнаты своих домов (максимальный размер файла, или ulimit). Хотя не установлен лимит на число различных файлов (комнат) максимального размера, которые могут существовать, вся систе- ма имеет предел (df показывает свободное пространство), и одна не- насытная персона может нанести удар по окружающим. Здесь возникает своего рода экология. Так же, как компьютерный век проходит под присмотром электронной автоматики, так и UNIX ведет таблицы о деятельности всех пользовате- лей. Механизмы учета организованы правительством (внутри ядра) и всег- да записывают действия каждого пользователя. Тем не менее, это свобод- ное общество в той мере, что вы можете получить распечатку о вашем кредитном состоянии (используя acctcom для печати учетных записей). Хотя система UNIX имеет негативные аспекты (как и человеческое общество), в ней есть также некоторые очень позитивные особенности. Гибкость системы и богатство инструментов дает нам очень продуктивную и детально разработанную рабочую среду. Наша производительность в этом смысле ограничена в основном нашим собственным воображением. Когда ра- бота становится слишком утомительной и скучной, мы всегда можем создать средства, делающие за нас эту работу. Это обстановка свободной инициа- тивы, в которой хорошие идеи могут дать значительное увеличение произ- водительности.  * ГЛАВА 2. Доступ к файлам *  СОДЕРЖАНИЕ Введение 2.1. Поиск файлов 2.1.1. tree - визуализация файлового дерева 2.1.2. thead - печать начала каждого файла 2.1.3. tgrep - поиск строк в дереве файловой системы 2.1.4. paths - нахождение пути доступа к исполняемым файлам, со специальными опциями 2.2. Вывод информации 2.2.1. lc - вывод файловой информации на экран по столбцам 2.2.2. ll - вывод файловой информации в длинном формате 2.2.3. kind - вывод однотипных файлов 2.2.4. m - простой доступ к команде more 2.2.5. mmm - обработка программой nroff макрокоманд для рукописей 2.2.6. pall - печать всех файлов в дереве ВВЕДЕНИЕ В главе 1 был представлен обзор общей структуры системы UNIX и показано, как взаимодействуют ее различные части. Это похоже на введе- ние в географию, когда на глобусе показывают континенты и крупные вод- ные пространства. Такая информация, хотя и является хорошим фундамен- том для общих знаний, вряд ли поможет найти наилучший путь из Сан-Франциско в Лос-Анжелес. Необходим следующий уровень детализации: названия поселений, дорог, развилок, улиц, адресов. Файловая система UNIX похожа на континент со множеством городов и, действительно, с адресами внутри городов. Каталоги и различные уровни подкаталогов можно сравнить с маршрутами между различными пунк- тами назначения, названия файлов - с адресами. Большое число путей и мест назначения может выглядеть пугающе, но благодаря регулярности и логичности, файловая система UNIX позволяет вам легко перемещаться из одного места в другое, если вы знаете несколько основополагающих принципов. Будучи пользователями UNIX, все мы научились пользоваться основ- ными командами файловой информации, как, например, ls с различными оп- циями. Мы знаем, как перемещаться между каталогами и копировать или перемещать файлы. Тем не менее, находить нужную информацию о файлах из всей массы информации не так-то легко. Нам необходимо создать инстру- ментальные средства, которые используют древовидную структуру файлов в UNIX, чтобы находить то, что мы ищем, и, соответственно, выводить ин- формацию о файлах на экран, печатать листинги содержимого файлов и т.д. Эта глава знакомит с инструментальными средствами, которые облег- чают задачу поиска и доступа к файлам. Доступ к файлам может быть обеспечен различными способами, поэтому техника и стиль меняются от одного командного файла к другому. Например, в некоторых случаях вам нужно найти имена всех файлов в данном сегменте файлового дерева, в других случаях вас будут интересовать файлы только заданного типа: текстовые файлы вообще или исходные файлы на языке Си в частности. КОМБИНИРОВАНИЕ ПРОДУКТИВНЫХ ИДЕЙ Две концепции являются общими почти для всех файловых инструмен- тальных средств. Первая - это идея рекурсивного поиска, которая озна- чает, что некоторые команды системы UNIX (например, find) просматрива- ют все файловое дерево, начиная с некоторой заданной начальной точки (или с текущего каталога). Если в данном каталоге встречается подката- лог, то его содержимое тоже исследуется - и так далее вниз к самому нижнему под-подкаталогу. Так проходятся маршруты ко всем файлам в це- лом дереве. Стандартные команды системы UNIX обеспечивают только ограниченное число основных функций, которые могут работать рекурсивно по всему файловому дереву. Наша стратегия при создании инструментальных средств в этой главе - воспользоваться преимуществами такого рекурсивного по- иска и распространить их на многие другие функции. Вторая ключевая идея, связанная с полезными файловыми инструмен- тальными средствами - это возможность соединения команд с программными каналами и управление потоком данных с помощью переадресации. Вероят- но, вы уже встречались с подобными особенностями в вашей собственной работе с UNIX и эффективно их использовали. Возможно, вы еще не осоз- нали, что соединение рекурсивного поиска, предоставляемого некоторыми стандартными командами, со специфическими функциями, предоставляемыми другими командами, позволяет нам создать команды, которые автомати- чески обходят обширные файловые деревья и извлекают нужную информацию. (В следующей главе мы выйдем за пределы распечатки и отображения ин- формации на экран и научимся работать с файлами так, что мы сможем ко- пировать, перемещать и восстанавливать их по мере надобности.) Для удобства мы сгруппируем инструментальные средства в два раз- дела: поиск файлов и распечатка файловой информации. Имеет смысл представлять их в таком порядке, так как вы сначала должны найти файл, чтобы потом с ним работать. ПОИСК ФАЙЛОВ Этот раздел посвящен поиску файлов, где бы они ни находились, вы- воду на экран выбранной информации и поиску символьных строк внутри файлов. Первая программа, tree, обходит все файловое дерево и печатает имена всех файлов в формате визуального дерева. Она рекурсивно спуска- ется в каждый каталог и находит все его файлы, обеспечивая тем самым глобальный осмотр файловых областей и их вложенной по глубине структу- ры. Другое инструментальное средство - это thead. Thead печатает несколько первых строк текстовых файлов, которые находятся в данном сегменте файлового дерева. Просматривая заголовок, т.е. первые несколько строк файла, вы можете получить достаточно информации, чтобы идентифицировать содержимое файла. При вызове thead вы можете явно за- дать каталог либо передать команде thead по конвейеру список полных имен файлов. Это делает команду thead фильтром - особым видом команд системы UNIX, который мы обсудим позже. Следующее инструментальное средство - tgrep. Как следует из наз- вания, это еще одна команда, связанная с файловым деревом, которая использует утилиту grep. Tgrep ищет символьные строки в каждом файле, который находится в данном сегменте файлового дерева. Tgrep также яв- ляется фильтром, так что имена файлов можно передавать ей по конвейе- ру. В нашем последнем проекте в этом разделе мы обратимся к использо- ванию каталогов как средства "навигации". Сначала мы опишем основной алгоритм для утилиты, которая для каждого файла из заданного списка файлов проверяет, находится ли этот файл в каком-либо каталоге по ука- занному маршруту поиска. Затем мы построим paths - утилиту, которая дополняет функцию поиска полезными опциями. РАСПЕЧАТКА ФАЙЛОВОЙ ИНФОРМАЦИИ Этот раздел знакомит вас с инструментальными средствами, предназ- наченными для вывода на экран имен файлов и их содержимого. Инструмен- ты такого рода весьма полезны, так как они могут значительно уменьшить количество необходимых символов, набираемых с клавиатуры при запуске команды, и внести больше смысла в одну команду. Первые два командных файла являются пре- и постпроцессорами для команды ls. Команда lc выводит файловую информацию по столбцам, коман- да ll перечисляет файлы в длинном формате. Эти командные файлы допол- нены опциями команды ls, чтобы сделать распечатки более информативны- ми. Так как команда ls используется довольно часто, упаковка наиболее часто применяемых нажатий клавиш в командные файлы представляется це- лесообразной. Упаковка уменьшает количество постоянно набираемых сим- волов и упрощает использование команд, исключает необходимость запоми- нания подробного синтаксиса. Третье инструментальное средство - это kind. Kind - еще один ко- мандный файл препроцессорного типа, использующий команду UNIX file. Команда file читает указанный файл и затем сообщает, является ли этот файл текстовым, архивным или исполняемым. Поскольку распечатки команды file не выбирают файлы заданного типа, возникает необходимость в соз- дании для этого специальной утилиты. Команда kind работает с распечат- кой команды file. Kind выводит на экран имена файлов только заданного типа. Еще один командный файл - m, который облегчает работу со стан- дартной командой more системы UNIX, уменьшая количество необходимых для запуска команды символов и упрощая интерфейс. Делается это без по- тери гибкости: так же, как вы можете использовать команду more для файла или передать команде more данные по программному каналу, вы мо- жете сделать то же самое для m. Следующий командный файл - это mmm. Он состоит из одной заготов- ленной командной строки для программы nroff системы UNIX. Существует много способов вызова команды nroff и множество различных опций к ней. Если же вы редко используете nroff, у вас могут возникнуть трудности в запоминании специфических опций, необходимых для вашей работы с коман- дой. Эти проблемы отпадут, если у вас есть команда mmm. Определите оп- ции, которые вы обычно используете, и введите их в командный файл mmm (о том, как это сделать практически, речь пойдет ниже). Теперь доста- точно набрать mmm - и вы имеете возможность работать с вашей командой nroff. Последняя утилита - pall. Pall обходит файловое дерево, ведя по- иск файлов заданного типа, и готовит их к выводу на принтер. Команда pr системы UNIX используется для разбивки на страницы всех файлов вместе и включения заголовков. Эта команда предлагает на рассмотрение принтеру один большой файл и наиболее полезна в тех случаях, когда у вас имеется множество каталогов с текстовыми файлами или с исходными файлами программ. Определив в общем основные наши задачи, перейдем к более близкому знакомству с упомянутыми инструментальными средствами. 2.1. ПОИСК ФАЙЛОВ 2.1.1. tree - визуализация файлового дерева ---------------------------------------------------- ИМЯ: TREE ---------------------------------------------------- tree - вывод на экран структуры файлового дерева НАЗНАЧЕНИЕ Находит все файлы в файловом дереве и выводит на экран имена фай- лов, показывая иерархическую структуру файлового дерева. ФОРМАТ ВЫЗОВА tree [dir] ПРИМЕР ВЫЗОВА $ tree $HOME Выводит структуру файлового дерева регистрационного каталога. ТЕКСТ ПРОГРАММЫ 1 : 2 # @(#) tree v1.0 Visual display of a file tree Author: Russ Sage 2а вывод на экран структуры файлового дерева 4 if [ "$#" -gt 1 ] 5 then echo "tree: wrong arg count">&2 6 echo "usage: tree [dir]" >&2 7 exit 2 8 fi 9 if [ "$#" -eq 1 ] 10 then if [ ! -d $1 ] 11 then echo "$0: $1 not a directory">&2 12 echo "usage: tree [dir]" >&2 13 exit 2 14 fi 15 fi 17 find ${1:-.} -print | sort | sed -e "1p" -e "1d" \ 18 -e "s|[^/]*/| /|g" \ 19 -e "s|[^ */|/|" \ 20 -e "s|/\([^/]*\)$|\1|" ОПИСАНИЕ ЗАЧЕМ НАМ НУЖЕН КОМАНДНЫЙ ФАЙЛ tree? Как мы уже отмечали, вся система UNIX строится вокруг файловой системы, которая похожа на дерево. Дерево, с которым мы работаем в системе UNIX, растет вверх ногами: корень находится вверху, а ветви и листва растут вниз от корня. Физическая структура реальных деревьев и файловых деревьев, используемых в системе UNIX, очень сходна: один ко- рень (начальная точка) и один ствол. Как глубоко и как далеко могут уходить ветви от основного ствола - не ограничивается ничем, кроме ог- раничений физического пространства. Аналогично, число листьев, которые может иметь каждая ветвь, фактически не ограничено. Многое в системе UNIX задумано для того, чтобы приспособиться к дереву. Некоторые команды обходят дерево и сообщают о его компонентах, но обычно их сообщения выдаются в форме, не очень удобной для чтения человеком. Это делает командные файлы весьма мощными инструментами. Перевести необработанные, недружественные сообщения командных файлов в удобный, информативный вид довольно легко. Команда tree является комбинацией команд системы UNIX, которые представляют логическую файловую структуру в наглядной форме. Эта ко- манда полезна для получения глобальной картины файлов, их расположения в иерархической структуре файлового дерева, гнездовой структуры ката- логов и подкаталогов. ЧТО ДЕЛАЕТ tree? Команда tree - это постпроцессор для команды UNIX find. Find просматривает сегмент файлового дерева и полные имена всех файлов, ко- торые соответствуют заданному критерию. Команда tree использует утили- ту sed системы UNIX, чтобы перевести выход команды find в наглядную форму. Входным параметром для команды tree является имя каталога, кото- рое может быть указано в любом абсолютном виде, например, /usr/spool/uucp, или в относительном, например, ../../bin. Если ника- кого имени не указано, подразумевается ., что является текущим катало- гом. Имя каталога является началом (или корнем) отображаемого дерева. Чтобы показать глубину дерева, все файлы, подчиненные данному катало- гу, отображаются с отступом. Для удобства представления гнездовой структуры, между следующими друг за другом ответвлениями печатается косая черта (/). Рассмотрим пример структуры каталога. Пусть корневым каталогом будет /tmp с двумя каталогами: a и b. В каталоге a находится подката- лог aa, который содержит файл file1, а в каталоге b , соответственно, подкаталог bb, содержащий файл file2. Команда find выдаст распечатку такого вида: # find /tmp -print /tmp /tmp/a /tmp/a/aa /tmp/a/aa/file1 /tmp/b /tmp/b/bb /tmp/b/bb/file2 Как видно из этого листинга, файлы a и aa есть каталоги, а файл file1 находится внизу файлового дерева. Сравните этот результат с ре- зультатом, который выдает команда tree, используя утилиту sed. # tree /tmp /tmp / a / / aa / / / file1 / b / / bb / / / file2 Корневым каталогом в этом листинге является каталог /tmp. Там, где дерево переходит на более глубокий уровень, печатаются только сим- волы косой черты. Первый уровень - /tmp, под этим уровнем находятся файлы-каталоги a и b, затем, соответственно, их подкаталоги aa и bb. Исходя из этого листинга, мы делаем вывод, что на первом уровне ката- лога находятся два файла (и эти файлы в действительности являются ка- талогами) и что два файла находятся в подчиненных каталогах. Отметим, что мы смогли идентифицировать aa и bb как каталоги только потому, что в них присутствуют файлы file1 и file2. Сравните этот листинг с выходом "необработанной" команды find. Выход команды tree исключает отвлекающее внимание повторение элементов путей доступа при каждом переходе к более низкому уровню. Благодаря этому, сразу же видно СУЩЕСТВЕННУЮ информацию. Вот что мы имеем в ви- ду, когда говорим о создании более наглядного для человека интерфейса с системой UNIX. ПРИМЕРЫ 1. $ tree Использует подразумеваемый каталог (текущий каталог, что рав- носильно команде "$ tree .") в качестве начала файлового дерева. 2. $ tree / Печатает древовидный листинг для КАЖДОГО файла всей системы. Ко- манда find при таком ее запуске начинает с корневого каталога и выдает информацию о всех файлах системы. 3. $ tree $HOME/.. Показывает древовидный формат для всех других пользователей системы (предполагается, что все пользовательские каталоги находятся в одном и том же каталоге, например /usr/*). ПОЯСНЕНИЯ Первая строка содержит только знак двоеточия (:) - "нулевую ко- манду". Это связано с тем, что все командные файлы, описываемые в этой книге, сделаны так, чтобы их можно было запускать в среде интерпрета- тора Bourne shell. Наш комментарий в строке 2, идентифицирующий версию, начинается со знака решетки (#). Си-shell ищет этот знак как первый знак командного файла. Если он найден, то предпринимается по- пытка выполнить данный командный файл. В противном случае Си-shell пе- редает командный файл интерпретатору Bourne shell. Вот почему мы не хотим начинать первую строку со знака #. Мы, конечно, могли бы оста- вить первую строку чистой, но чистая строка невидима и может быть слу- чайно удалена. Соответственно мы будем использовать чистые строки в других случаях, чтобы выделить важные участки программы. Строка 2 идентифицирует версию. Символьная строка @(#) есть спе- циальная последовательность в строке комментария, которая распознается как строка "what" ("что"). Команда what в системе UNIX читает файл и печатает сообщение, которое следует за строкой "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 обеспечивает согласованное поведение командного файла независимо от среды, в которой он запущен. Отметим