Ключ -o выполняет то же самое для файлов, соответствующих *.o.
Примеры
1. $ mount /dev/fd0 /mnt
$ cp /usr/include/* /mnt
$ dsum /usr/include /mnt
Монтирует гибкий диск в каталог /mnt. Копирует все файлы заголов-
ков в каталоге /usr/include на гибкий диск. Проверяет копии, используя
dsum для исходного каталога и для каталога с копией.
Примечание: Указывая копировать *, мы вообще не попадем
в каталог /usr/include/sys.
2. $ dsum . ..
Используя в качестве управляющих файлов файлы в текущем каталоге,
сверить каждый файл с одноименным файлом в родительском каталоге.
Пояснения
В строках 4-9 производится проверка на наличие ошибок. Если указа-
но менее двух аргументов, значит управляющий каталог и/или каталог ко-
пии не указан и в результате обнаруживается ошибка. Если количество ар-
гументов превышает три, значит, указано еще что-то кроме ключа -c и
двух каталогов, что также является ошибкой. Все остальное (два или три
аргумента) рассматривается как допустимое значение.
В строках 11-21 производится инициализация переменной FLIST. FLIST
- это управляющая переменная, которая определяет имена файлов, на кото-
рые надо обратить внимание. Если в командной строке указаны только име-
на каталогов ($# = 2), FLIST присваивается значение по умолчанию * (все
файлы) в строке 12. Значение * присваивается переменой FLIST и не трак-
туется в это время как метасимвол (это особенность командного процессо-
ра). Если в командной строке указан ключ ($# = 3), производится провер-
ка первой переменной и FLIST получает соответствующее значение, *.c или
*.o. Если указана не такая опция, выводится сообщение об ошибке и прог-
рамма завершается.
В строках 23-31 выполняется сама работа. Здесь выполняется цикл
for, который проходит по списку слов, созданному управляющим каталогом
в соответствии со значением переменной FLIST. В строке 23 переменная
FLIST расширяется фактически с символа * в имя каждого файла. Тем самым
цикл for получает данные для использования. Следовательно, переменная
FLIST является полным маршрутным именем каждого файла в управляющем ка-
талоге.
Строка 25 разбирает расширение, сделанное в строке 19. Переменная
BASEF получает базовое имя полного маршрута из переменной FILE. Причи-
ной, по которой мы это делаем, является тот факт, что позже при ссылке
на каталог копии нам необходимо только имя файла. (В системе UNIX ко-
манда basename возвращает последний элемент в указанном маршруте, т.е.
само имя файла, если маршрут содержит промежуточные каталоги.)
Строки 26-29 выводят первую часть выходного сообщения. Оператор
if-then использован потому, что нам нужно менять выходное сообщение в
зависимости от того, сколько символов содержит имя файла. Строка 26 оп-
ределяет длину имени файла, используя команду expr. Команда expr может
быть использована для сравнения двух строк и получает количество сов-
павших символов. Сравнение имени файла со "всеми символами" (*), таким
образом возвращает длину строки. (У вас может возникнуть желание обра-
титься к expr(1), чтобы получить информацию о других хитростях этой
многоцелевой команды.)
Это возвращаемое значение используется в операторе test для опре-
деления, содержит ли имя файла менее семи символов: возможно всего один
или два символа. В последнем случае, если мы делаем табуляцию, мы полу-
чим только первую позицию табуляции. Для получения последующих табуля-
ций мы отображаем семь символов для того, чтобы попасть на место следу-
ющего поля табуляции. (Если было 3-6 символов, мы все равно остановимся
на поле второй табуляции, т.е. это место работает верно.) Затем отобра-
жаем табуляцию для того, чтобы мы попали на место окончания второй та-
буляции, что нам и требовалось.
Если имя файла содержит более семи символов, мы уже находимся в
первой позиции табуляции или за ней. Таким образом, следующий символ
табуляции передвинет нас во вторую позицию табуляции. Эффект заключа-
ется в том, что для размещения колонок не имеет значения размер имени
файла (кроме случая, когда оно действительно очень длинное). Это позво-
ляет избавиться от "блюза ползущих колонок", когда колонки сдвигаются в
зависимости от размера отображаемой информации. В качестве примера та-
кого эффекта может служить стандартная команда sum. Ее выход выглядит
так:
--------------------------------
| 4243 3 autobkp
| 247 1 can
| 25167 6 cpiobr
| 186 3 dosflp
| 56864 2 dsum
| 2782 1 log
|
С другой стороны, выход dsum очень ясный и четкий, не сдвигается
по всему экрану. Сдвиг делает вывод изломанным и затрудняет быстрый
просмотр информации.
Чудо вывода в одну строку совершается в строке 27 (для файлов с
именами менее 7 символов) или в строке 28 (для файлов с более длинными
именами). Внутри команды echo в каждом случае мы прячем другие команды,
но по-прежнему управляем тем, как их результаты выводятся на экран.
Во-первых, сами имена файлов выводятся, будучи ранее извлеченными из
полного маршрутного имени. Обратите внимание, что имена файлов не со-
держат информацию о том, из какого они каталога. Затем мы несколько
сдвигаемся и печатаем первое поле выходной суммы для этого файла (саму
контрольную сумму). Это контрольная сумма версии файла в управляющем
каталоге, поскольку переменная FILE была сгенерирована для этого ката-
лога. Команда sum выводит три значения (контрольная сумма, число бло-
ков, занятых файлом, и само имя файла). Нам нужно получить только пер-
вое значение, которое извлекается путем выполнения команды sum и пере-
дачи ее выхода по каналу команде cut, которая и возвращает первое поле.
После того, как значение контрольной суммы напечатано, мы отображаем \c
для запрещения перехода на новую строку. Это сохраняет курсор в той же
строке.
Здесь начинает работать строка 30. Она генерирует контрольную сум-
му того же файла в каталоге копии ($2 в командной строке) и текущее имя
файла, вырезая только число, и печатает его правее курсора в той же
строке.
Цикл завершается, когда все файлы из управляющего каталога будут
проверены командой sum.
ВОЗМОЖНЫЕ МОДИФИКАЦИИ КОМАНДНОГО ФАЙЛА
Неплохой модификацией может быть вариант, чтобы dsum печатала не
только значения, как это сделано, но и флаг в конце строки в случае,
когда два файла отличаются. Тогда у нас не было бы необходимости
просматривать непосредственно числа. Мы ищем флаг и сразу видим, когда
что-то не так.
Ниже приводится решение проблемы вывода флага для того, чтобы об-
легчить вам работу. Оно не включено в представленную выше утилиту по
той причине, что такого рода вещи могут быть выполнены относительно
просто. Вы можете сами сделать эту модификацию в качестве упражнения.
Текст программы, выполняющей эту работу, выглядит так:
for FILE in $1/$FLIST
do
BASEF=`basename $FILE`
S1=`sum $FILE 2>&1 | cut -d' ' -f1`
S2=`sum $2/$BASEF 2>&1 | cut -d' ' -f1`
if [ "$S1" = "$S2" ]
then M=""
else M="<---"
fi
if [ ` expr $BASEF : '.*'` -lt 7 ]
then echo "$BASEF: \t$S1\t$S2 $M"
else echo "$BASEF:\t$S1\t$S2 $M"
fi
done
Подход к решению немного отличается от решения, принятого при на-
писании dsum, поскольку вы не можете генерировать контрольную сумму на
ходу. Вы должны перехватить выход команды sum и использовать его позже.
То, что мы ищем, появляется в шестой строке. Если две контрольные суммы
различны, переменная M устанавливается соответствующим образом. Если
файлы различаются, переменная M получает стрелку, указывающую на то,
что копия плохая.
3.4.2. log - меню доступа к файлам протокола копирования
---------------------------------------------------------------------------
Имя : log
_________________________________________________________________________
log Меню доступа к файлам протокола копирования
НАЗНАЧЕНИЕ
Обеспечивает интерфейс в виде меню к файлам протокола, полученным
от утилиты autobkp.
ФОРМАТ ВЫЗОВА
log
Пример вызова
log
Командный файл log
1 :
2 # @(#) log v1.0 Menu access to backup logfiles Author: Russ Sage
4 c
5 set `date`
6 echo "
8 $1, $2 $3 $4
10 Logfile Menu
11 ----------------
12 1 - list all log file names
13 2 - display log of home backup
14 3 - display log of product backup
15 to exit
17 Enter command (1-3,<>): \c"
18 read CMD
20 case $CMD in
21 "") exit;;
22 1) echo "\nLogfile names:"
23 sed -n -e "/more/s/^.*more \(.*\);;$/\1/p" $HOME/bin/log;;
24 2) more $HOME/bin/autobkplog.home;;
25 3) more$HOME/bin/auto2.bkplogm;;
26 *) echo "log: $CMD is not a command";;
27 esac
Переменные среды выполнения
CMD Команда, полученная от пользователя
HOME Ваш регистрационный каталог в системе
Описание
Зачем нам нужен log?
Если вы читали эту главу, ничего не пропуская, вы уже встречались
с программой autobkp. Выводные данные autobkp очень информативны и
должны быть сохранены как часть операции копирования. Это еще более
важно, если у вас имеются программы, запускаемые с помощью cron. Со
временем некоторые из этих программ может начать работать неверно и
разрушить все вами сделанные копии. Единственный способ проследить за
такими вещами - это использовать файлы протокола. Файлы протокола ко-
манды cron содержат некоторую информацию, но файлы протокола программы
autobkp содержат ее гораздо больше.
Проблема возникает, когда вы сталкиваетесь с наличием нескольких
работ для autobkp. Вы можете не захотеть смешивать невзаимосвязанные
копии файлов в одном и том же файле со списком маршрутов, поэтому вы
создаете несколько файлов pathlist, несколько заданий для cron и
несколько файлов протокола. Если вам нужно выполнить пять или десять
подобных работ, каким образом вы проследите за всеми файлами протоко-
лов, запомните их имена и облегчите их просмотр? Все эти проблемы реше-
ны в командном файле log.
Что делает log?
Командный файл log - это управляемая при помощи меню утилита. Меню
позволяет вам видеть текущие имена файлов в файлах протокола, поэтому
вам нет необходимости помнить их. Остальные команды являются входными
точками в файлы протокола, использующими команду more для просмотра.
Когда мы рассматривали командный файл cpiobr, мы видели, как рабо-
тает управляемая при помощи меню программа. Командный файл log несколь-