Зачем нам нужен командный файл
Зачем нам нужен командный файл tree?
Как мы уже отмечали, вся система UNIX строится вокруг файловой системы, которая похожа на дерево. Дерево, с которым мы работаем в системе UNIX, растет вверх ногами: корень находится вверху, а ветви и листва растут вниз от корня. Физическая структура реальных деревьев и файловых деревьев, используемых в системе UNIX, очень сходна: один корень (начальная точка) и один ствол. Как глубоко и как далеко могут уходить ветви от основного ствола - не ограничивается ничем, кроме ограничений физического пространства. Аналогично, число листьев, которые может иметь каждая ветвь, фактически не ограничено.
Многое в системе UNIX задумано для того, чтобы приспособиться к дереву. Некоторые команды обходят дерево и сообщают о его компонентах, но обычно их сообщения выдаются в форме, не очень удобной для чтения человеком. Это делает командные файлы весьма мощными инструментами. Перевести необработанные, недружественные сообщения командных файлов в удобный, информативный вид довольно легко.
Команда tree является комбинацией команд системы UNIX, которые представляют логическую файловую структуру в наглядной форме. Эта команда полезна для получения глобальной картины файлов, их расположения в иерархической структуре файлового дерева, гнездовой структуры каталогов и подкаталогов.
Что делает tree?
Команда tree - это постпроцессор для команды UNIX find. Find просматривает сегмент файлового дерева и полные имена всех файлов, которые соответствуют заданному критерию. Команда tree использует утилиту sed системы UNIX, чтобы перевести выход команды find в наглядную форму.
Входным параметром для команды tree является имя каталога, которое может быть указано в любом абсолютном виде, например, /usr/spool/uucp, или в относительном, например, ../../bin. Если никакого имени не указано, подразумевается ., что является текущим каталогом.
Имя каталога является началом (или корнем) отображаемого дерева. Чтобы показать глубину дерева, все файлы, подчиненные данному каталогу, отображаются с отступом. Для удобства представления гнездовой структуры, между следующими друг за другом ответвлениями печатается косая черта (/).
Зачем нужен командный файл 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.
Зачем нам нужен командный файл 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 является фильтром.
ЗАЧЕМ НАМ НУЖЕН КОМАНДНЫЙ ФАЙЛ paths?
В нашей среде интерпретатора shell переменная с именем PATH содержит имена каталогов, отделенные друг от друга символами двоеточия (:). Каждый раз, когда вы вводите команду после приглашения shell'а, интерпретатор shell, начиная с первого каталога, указанного в переменной PATH, смотрит, находится ли введенная вами команда в этом каталоге. Если да, то команда выполняется. Если нет, то shell идет в следующий каталог, указываемый переменной PATH, и так далее, пока не будут проверены все каталоги. Если команда все же не будет найдена, то вы получите следующее сообщение об ошибке:
| | $ whatchamacallit | sh: whatchamacallit: not found | |
Такой поиск команды осуществляется автоматически, но сама система не сообщает вам, ГДЕ размещена команда. Нам необходима утилита, которая ищет и выводит на экран маршрут к указанному файлу. Имея такую утилиту, вы можете использовать кратчайшие пути получения того, что вам нужно, и выполнять множество различных трюков. Вы можете комбинировать подобную команду с другими командами для создания гораздо более мощных средств. С маршрутом можно также комбинировать команды more, ls, file и cd системы UNIX. Возможно, вы обнаружите и другие команды по мере экспериментирования.
Команда, несколько похожая на ту, которую мы ищем, существует где-то в мире системы UNIX Systev V. Например, в системе AT&T это команда where. В системе UNIX Berkeley это команда which (текст на языке Си-shell'а) или whereis (исполняемая программа). Whereis дает дополнительную информацию, такую как место размещения файлов с исходными текстами (в каталоге /usr/src). Увидев, как мы создаем нашу собственную команду поиска маршрута, вы можете модифицировать ее для обеспечения работы с особенностями некоторых других команд и приспособить такие вещи к вашим нуждам.
Прежде чем мы удовлетворим свои прихоти, давайте бегло глянем на команду path, более простую, чем paths. Вся программа выглядит примерно так:
IFS="${IFS}:" for FILE in $@ do for DIR in $PATH do if [ -f $DIR/$FILE ] then echo $DIR/$FILE fi done done
ЗАЧЕМ НУЖЕН КОМАНДНЫЙ ФАЙЛ kind?
Файловая система UNIX имеет строгие стандарты при рассмотрении файлов. Имеется три вида файлов: обычные файлы (тексты, данные, исполняемые файлы), каталоги и устройства. Каждый вид файлов имеет свое предназначение и обычно имеет особые команды или файлы данных, которые работают с ним.
Давайте рассмотрим, как некоторые из существующих команд системы UNIX рассматривают типы файлов. Команда ls делает различие между каталогами и другими файлами, поэтому она может быть полезна. Другой важной командой является команда file. Она сообщает вам, какой тип имеет данный файл, что потенциально полезно, но слишком мало. Для того чтобы извлечь из команды file какую-либо полезную информацию, вы должны надстроить над ней некоторую программу. Что нам действительно нужно, так это некий гибрид команд ls и file, т.е. утилита, которая выводит имена всех файлов указанного типа.
Примером полезности такого рода утилиты может служить анализ содержимого каталогов. Возьмем, например, каталог /etc. Он содержит программы, файлы данных и текстовые файлы. Для каждого из этих типов требуется свой собственный тип анализа. Программы анализируются командами ls, size, nm и file. Файлы данных анализируются командой od.
Текстовые файлы анализируются командами more, wc, head, tail и другими. Таким образом, обычно вам необходимо работать в данный момент времени с файлами какого-нибудь одного типа.
ЧТО ДЕЛАЕТ kind?
Командный файл kind - это утилита, которая распечатывает имена всех файлов, имеющих указанный тип. Она имеет интерфейс, похожий на интерфейс команды ls, т.е. вы можете передать ей опции и имена файлов или символы расширения имен файлов. При выводе отображаются полные имена, если они были указаны, но вы можете избежать появления лишней информации при выводе, если предварительно перейдете в нужный каталог с помощью команды cd. Например, если бы я находился в моем регистрационном каталоге (/usr/russ) и ввел команду
$ kind -d /etc/* то вывод мог бы выглядеть так: | | /etc/mnttab | /etc/utmp | /etc/wtmp |
Зачем нам нужен командный файл ll?
Мотивы для создания команды ll те же, что мы обсудили ранее для команды lc. Мы можем использовать ll для нескольких целей. Она уменьшает количество требуемых нажатий на клавиши, позволяет избежать необходимости помнить специальные опции и вообще настраивает систему соответственно нашим требованиям вместо того чтобы нам приспосабливаться к системе.
Что делает ll?
Основой этой команды является известная команда "ls -l". Она, если вы помните, дает очень емкую информацию о каждом файле, включая права доступа, связи, имя владельца, размер и так далее. (Кстати, программисты, использующие язык Си, могут получить эту информацию при помощи системного вызова stat(2).) Поскольку такой список при наличии множества файлов может легко переполнить экран, то предоставляется опция -m. Она обеспечивает постраничный вывод с помощью команды more. Отметим, что если используется эта опция, то она должна стоять первой. Строка символов, соответствующая этой опции, удаляется командой shift, так что она не смешивается с именами файлов и обычными опциями команды ls, которые передаются как аргументы.
После опции -m (если она есть) ll допускает указание любых других допустимых опций команды ls. Можно также использовать любую комбинацию имен файлов. Здесь применимы обычные средства порождения имен файлов: * соответствует любым символам, ? - одному символу, а символы [] задают диапазон из некоторого набора символов. В итоге мы получили команду ls, которая по умолчанию работает как "ls -l", вызывает команду more с помощью одной опции вместо необходимости указания конвейера в командной строке и при этом сохраняет гибкость команды ls.