Ключевой командой является комбинация ls-grep. Каждое имя файла в
каталоге распечатывается в длинном формате, затем просматривается бит
установки пользовательского идентификатора. Модель такова, что команда
ls -al $DIR печатает следующее:
---------------------------------------------------------------------------
|
| -rws--x--x 1 root bin 16235 Sep 13 1985 /bin/su
|
|
Аргумент "^[^ ]*s[^ ]*" означает поиск от начала строки символа,
отличного от пробела, за которым следует один или более символов, от-
личных от пробела, затем символ s и затем один или более символов, от-
личных от пробела. Это выражение ограничивает поиск битами прав досту-
па в начале строки. Если имеется символ s где-либо в правах доступа
(либо в пользовательском идентификаторе процесса, либо в групповом
идентификаторе процесса), то команда grep отрабатывает успешно и печа-
тается вся строка.
Такой вид поиска установленного пользовательского идентификатора
несколько "легковесен" в том смысле, что поиск ведется только согласно
переменной PATH, которая у вас есть. Файлы с установленным пользова-
тельским идентификатором могут находиться в каталогах, которые не ука-
заны в PATH. Однако в такой реализации данная опция обеспечивает быст-
рое обращение к вашим локальным файлам с установленным пользова-
тельским идентификатором.
ВОЗМОЖНЫЕ МОДИФИКАЦИИ
Данный командный файл открыт для многих различных видов модифика-
ции. Поиск полного имени файла является фундаментальной задачей прог-
раммного обеспечения по сопровождению файлов. Эта возможность позволя-
ет нам полагаться на саму программу paths или использовать paths в ка-
честве куска более объемной программы.
При разработке ваших собственных программ следует обратить внима-
ние на гибкость командного файла paths, которая выражается в отличии
между обрабатываемыми форматами. Первые два формата используют отдель-
ные файлы, а формат set использует каталоги. Дальнейшие дополнения к
командному файлу paths могут касаться любой из этих строк или могут
комбинировать их. Если есть необходимость, программное обеспечение мо-
жет приспособиться к этому.
2.2. ВЫВОД ИНФОРМАЦИИ
2.2.1. lc - вывод файловой информации на экран по столбцам
---------------------------------------------------------------------------
ИМЯ: lc
---------------------------------------------------------------------------
lc Выдает список файлов в колоночном формате
НАЗНАЧЕНИЕ
Выдает информацию о файлах в формате колонок, показывая каталоги
и исполняемые модули. Этот листинг можно пропустить через команду
more.
ФОРМАТ ВЫЗОВА
lc [-m] [ls options] file [file ...]
ПРИМЕР ВЫЗОВА
lc -R $HOME
Выдает список всех файлов во всех подкаталогах моего регистра-
ционного каталога.
ТЕКСТ ПРОГРАММЫ
1 :
2 # @(#) lc v1.0 List files in a column Author: Russ Sage
2а Выводит список файлов в колоночном виде
4 if [ "$1" = "-m" ]
5 then MORE="| /usr/bin/more"
6 shift
7 else MORE=""
8 fi
10 eval "/bin/ls -a $@ | /bin/pr -5t" $MORE # pre System V
11 eval /bin/ls -aCF $@ $MORE # System V
ПЕРЕМЕННЫЕ СРЕДЫ ВЫПОЛНЕНИЯ
MORE Содержит программный канал к команде more
ОПИСАНИЕ
ЗАЧЕМ НАМ НУЖЕН КОМАНДНЫЙ ФАЙЛ lc?
В мире компьютеров многие люди изобретают колесо, а другие люди
изобретают его снова. Если первое колесо не того размера или не того
цвета, делается другое колесо. В нашей конкретной ситуации исходным
колесом является команда ls системы UNIX, которая имеет некоторые не-
достатки в своих ранних реализациях. Она выдает хорошую информацию, но
она печатает имена файлов только в одну колонку, что приводит к нера-
циональному расходованию места и затрудняет чтение имен файлов. Поэто-
му мы создаем версию команды ls, которая отображает распечатки в
несколько колонок.
Как видно из предыдущего листинга, lc имеет две формы. Одна пред-
назначена для систем, более ранних, чем System V, а другая - для
System V и последующих версий UNIX. Причина в том, что System V версии
2 имеет новую команду ls, которая делает именно то, что мы хотим.
Система Berkeley также имеет версию команды ls, которая по умолчанию
использует несколько колонок при выводе на терминал. Но для XENIX и
ранних версий System V мы должны делать это сами. Дело в том, что хотя
в вашей версии UNIX, XENIX или чего-либо еще могут отсутствовать ко-
манды, имеющиеся в других версиях, вы обычно можете построить то, что
вам нужно. Это может потребовать определенных усилий, и ваши программы
могут работать не так быстро и не так эффективно, но вы МОЖЕТЕ полу-
чить нужное средство.
Пользователям интерпретаторов csh и последнего sh, имеющего функ-
ции, видимо, лучше бы заменить весь этот сценарий на то, чтобы сделать
lc псевдонимом (alias). Использовать возможность введения псевдонимов,
чтобы присвоить имя любой корректной командной строке UNIX (например,
вызову команды ls с указанными опциями). Это легче, чем писать команд-
ный файл, но ограничивает вас необходимостью работать с уже имеющимися
командами или опциями. Это быстрее, так как не создается никаких до-
полнительных процессов.
При работе со старым интерпретатором sh мы должны пройти через
обычную процедуру изготовления командного файла и размещения его в ка-
талоге bin. С другой стороны, SCO XENIX System V решает эту проблему,
связывая эти же имена (lc, lf, l) с обычной командной ls и используя
вызывающее имя для определения формы распечатки.
Итак, зачастую имеется много альтернатив. Мастера UNIX, сталкива-
ясь с какой-либо проблемой, не борются с ней с помощью Си или команд-
ного файла интерпретатора shell. Поскольку они знакомы с существующими
ресурсами системы UNIX, они могут рассмотреть проблему и выбрать стра-
тегию, использующую наименее сложное средство, выполняющее данную ра-
боту с приемлемым уровнем производительности. В порядке возрастания
сложности, это могут быть непонятная, но существующая команда и/или
опция, псевдоним, командный файл интерпретатора shell или программа на
языке Си.
ЧТО ДЕЛАЕТ lc?
Общий подход к разработке этой команды заключается в том, чтобы
собрать вместе некоторые опции и сделать новую команду с более мощным
интерфейсом. Чтобы достичь этой мощи, мы можем сделать пре- или пост-
процессор для обычной команды системы UNIX.
Главная задача здесь - печать колонок, поэтому мы смотрим на оп-
ции команды ls, чтобы задействовать их. Конечно, мы включаем опцию -C.
Какие еще опции ls нам нужны? Обычно UNIX не печатает файлы, имена ко-
торых начинаются с точек, например, .profile, если только вы не указы-
ваете ls -a. Это забывается при просмотре этих важных файлов, поэтому
мы конструируем нашу команду так, чтобы она печатала их по умолчанию.
Никакие файлы не скрываются от нас. Для пользователей System V и BSD
(или для любого, кто имеет опцию -F), листинг улучшается за счет выво-
да "/" после имени каталога и "*" после исполняемого файла. Ранняя ко-
манда ls системы UNIX не имела возможности печатать в таком стиле. От-
метим, что данное использование термина "исполняемый" означает показ
того, что флаги прав доступа имеют бит "x", а не то, что это файл типа
a.out с магическим числом. Это отличие важно тем, что делает наш ко-
мандный файл более полезным.
Если ожидается длинная распечатка, как это бывает обычно для ре-
курсивных каталогов, то вы хотите иметь доступ к команде more. Мы
встраиваем команду more так, чтобы ее можно было активировать с по-
мощью опции -m. Опция -m должна быть первой опцией после имени коман-
ды, из-за способа, которым она проверяется внутри программы. Если она
передается после первой опции, она переходит к команде UNIX ls и ин-
терпретируется как печать в потоковом формате. Это такой формат, в ко-
тором все имена расположены в строках, разделенных запятыми (,). Как
мы уже отмечали, вы можете сделать интерфейс этого командного файла
более гибким за счет дополнительной работы над ним.
ПРИМЕРЫ
1. $ lc `path lc`
Получает полное имя для lc и распечатывает файловую информацию в
виде колонок.
2. $ lc -m -R /
Печатает колоночный список ВСЕХ файлов в системе, рекурсивно про-
ходя вниз по иерархии системного дерева и пропуская распечатку через
команду more.
Еще один маленький фокус: этот синтаксис был использован для соз-
дания другой команды, названной expose. Командная строка "lc -m -R $@"
давала бы рекурсивный список всех файлов в любом каталоге по вашему
выбору в приятном постраничном формате.
3. $ lc -m -R /usr/lib
Рекурсивно распечатывает список всех файлов во всех каталогах,
начиная с /usr/lib, и пропускает листинг через команду more.
4. $ lc -m . | more
Выдает список файлов в текущем каталоге и пропускает листинг че-
рез команду more, а затем снова пропускает все через more. Работает ли
это ? Никоим образом. Возникает полная путаница, и клавиша прерывания
обычно является наилучшим способом выхода из данной ситуации.
ПОЯСНЕНИЯ
В строках 4-8 проверяется, является ли первым аргументом команд-
ной строки -m - опция команды more. Если эта опция найдена, то в пере-
менную MORE заносится указание конвейера и команда more. Тем самым
устанавливается постобработка, которую следует применить к выходу ко-
манды ls. Затем эта опция убирается из командной строки. Это делается
для того, чтобы остаток командной строки можно было передать команде
ls, не вызвав при этом нежелательных эффектов. Если первой опцией не
является -m, переменной MORE присваивается нулевое значение, чтобы она
впоследствии не влияла на командную строку.
Строка 10 - это командная строка, которую вы бы использовали на
старой UNIX-машине типа Version 7 или System III. Она не имеет ни
встроенной опции для печати символов косой черты (/) и звездочек (*),
ни возможности печати в виде колонок. Вы должны пожертвовать первой
возможностью, а распечатки в виде нескольких колонок можно получить с
помощью команды pr системы UNIX. Команда pr использована с опцией
"-5t", поэтому она печатает в пять колонок (что обычно приемлемо, но
если встречаются длинные имена файлов, то пяти колонок может оказаться
слишком много) и не печатает верхний и нижний колонтитулы. Благодаря
отказу от колонтитулов, 24-строчный формат не слишком неудобен для
вас.
Отметим, что здесь использована команда eval. Это специальная
встроенная команда интерпретатора shell, которая выполняет перевы-
числение текущей строки, подлежащей выполнению. Интерпретатор shell
повторно анализирует эту строку, чтобы раскрыть значение имен перемен-
ных в командной строке и обеспечить распознавание переменных как тако-
вых. Здесь мы перевычисляем переменную MORE. Напомним, что мы помести-
ли в эту переменную конвейер. Если мы не перевычислим командную стро-
ку, то команда pr попытается открыть файлы "|" и "more", которые не
существуют. Для того, чтобы shell вместо этого воспринял эти символы
как указания конвейеров и программ, и используется команда eval.
Строка 10 имеет еще одну особенность. В командной строке уже есть
один конвейер. Откуда shell знает, трактовать ли символ "|" как имя
файла или как конвейер? Благодаря тому, что аргумент команды eval зак-
лючен в кавычки. Это указывает команде eval сохранить все, что нахо-
дится в кавычках, без изменений, но раскрыть значение переменной MORE
и поместить его в конец командной строки, находящейся в кавычках.
Несколько непонятно, но если вы думаете об этом пару лет, оно стано-