Новые книги

Эта книга – набор методик, приемов и секретов по написанию продающих текстов (текстов для сайтов, полиграфии, коммерческих предложений и других рекламных целей). Каждая глава содержит совет или прием, готовый к использованию, – например, как написать эффективный заголовок для текста. Читатель открывает книгу на нужной странице, выбирает необходимый ему совет или секрет и внедряет его. Весь материал издания построен на успешном личном опыте автора и его клиентов. Здесь нет теории, нет сложных систем и заумных формул – только практика, состоящая из отборных приемов по написанию рекламных текстов. Настоятельно рекомендуется копирайтерам, неймерам, маркетологам, специалистам в области рекламы и PR, владельцам малого и среднего бизнеса.
Вы занимаетесь продажами? Тогда вам наверняка знакомо чувство отчаяния из-за непредсказуемого поведения ваших клиентов или ваших собственных действий, оказавшихся ошибочными. Хотя вы, казалось бы, все просчитали.

Дэвид Сэндлер начал карьеру в отделе продаж, будучи разорившимся бизнесменом. Спустя некоторое время он ушел, чтобы… открыть собственную компанию по обучению технике продаж. Очень скоро Сэндлер приобрел широкую известность, а 49 неочевидных, провокационных, но действенных «правил Сэндлера» вошли в арсенал многих успешных продавцов.

Книга адресована всем, кто продает – товары, услуги, мысли, идеи. Постоянно или время от времени.

ГЛАВА 3. Поддержка файловой системы


3.2.3. dosflp - копирование файлов с гибкого диска формата MS-DOSс использованием символов шаблона в именах файлов


    Имя: dosflp

dosflp Копирование файлов с гибкого диска формата DOS с использованием символов шаблона в именах файлов

НАЗНАЧЕНИЕ

Копирует файлы с гибкого диска в формате DOS (в XENIX) на жесткий диск. Обеспечивает возможность использования записи с помощью символов-шаблонов для имен файлов на гибком диске, где такая запись обычно недопустима.

ФОРМАТ ВЫЗОВА
         dosflp [-a] [-c] [-dDRIV] [-eEXP][-h] [-l] [-r] [-sDIR]

где

-a означает копирование файлов, соответствующих *.asm
-c означает копирование файлов, соответствующих *.c
-d выбирает имя устройства DRIV из набора A,B,X,Y (по умолчанию A)
-e использует выражение EXP, чтобы применить к файлам grep
-h копирует файлы, соответствующие *.h
-l только выдает список файлов
-r удаляет файлы вместо их копирования
-s указывает подкаталог DIR на гибком диске формата DOS
ПРИМЕР ВЫЗОВА

dosflp Копирование всех файлов с устройства A: в текущий каталог

ИСХОДНЫЙ КОД ДЛЯ DOSFLP
    1  :
    2  # @(#) dosflp v1.0  Wildcard copies from DOS floppy
                    Author: Russ Sage
     
    4  EXP=.\*
    5  DRIVE="A:"
    6  OP="c"
     
    8  if [ "$#" -gt 0 ]
    9    then  for ARG in $@
    10          do
    11          case "$ARG" in
    12          -a)  EXP='.*\.asm$';;
    13          -c)  EXP='.*\.c$';;
    14          -d*) DRIVE="`echo $ARG | cut -c3-`:";;
    15          -e*) EXP='`echo $ARG | cut -c3-`';;
    16          -h)  EXP='.*\.h$';;
    17          -l)  OP="l";;
    18          -r)  OP="r";;
    19          -s*) DRIVE="$DRIVE`echo \"$ARG" | cut -c3- `/";"
    20          *)   echo "dosflp: arg error"
    21               echo "usage: dosflp [-a] [-c] [-d] [-e] [-h] [-l]
     [-r] [-s]"
    22               exit 1;;
    23          esac
    24       done
    25 fi
     
    27 case $OP in
    28 c)  echo "\nCopying files from $DRIVE to `pwd`";;
    29 l)  echo "\nListing files on $DRIVE"
    30     dosdir $DRIVE | more
    31     exit;;
    32 r)  echo "This option removes all the data on the floppy."
    33     echo -n "Do you want to do this (y/n): "
    34     read RSP
    35     if [ "$RSP" = "y" ]
    36       then  echo "\nRemoving files on $DRIVE"
    37       else exit
    38     fi;;
    39 esac
     
    41 dosls $DRIVE | tr "[A-Z]" "[a-z]" > /tmp/doslist
     
    43 for FILE in `grep "$EXP" /tmp/doslist`
    44 do
    45         echo $FILE
    46         case $OP in
    47         c)  doscp $DRIVE$FILE .;;
    48         r)  dosrm $DRIVE$FILE;;
    49         esac
    50 done
     
    52 rm /tmp/doslist
     
ПЕРЕМЕННЫЕ СРЕДЫ ВЫПОЛНЕНИЯ
ARG Хранит аргументы командной строки
DRIVE Устройство с гибким диском формата DOS
EXP Выражение, имитирующее действие символа-шаблона
FILE Хранит имя файла, над которым производится действие
OP Ключ, определяющий необходимое действие
ОПИСАНИЕ

Зачем нам нужен dosflp?

Это команда только для системы XENIX. Операционная система XENIX, являясь продукцией фирмы Microsoft, имеет средства для общения с файловой системой MS-DOS. Для ознакомления с основами совместного использования DOS и XENIX давайте рассмотрим основные параметры.

Каждый жесткий диск может иметь максимум четыре раздела. Это ограничение MS DOS, которое перенесено в мир XENIX. Ничего плохого в этом нет, пока мы не начинаем работать с жестким диском большой емкости. Для70-мегабайтного диска, например, вы можете создать четыре равных раздела, каждый из которых содержит приблизительно 17 Мбайт. Вы можете создать меньший раздел, но тогда другой раздел должен быть больше. В зависимости от того, какая часть ваших программ и данных должна быть использована в основном MS-DOS и какая - XENIX, может быть использована различная конфигурация.

Большим преимуществом системы XENIX/DOS является то, что XENIX может размещаться в одном разделе, а DOS в другом. Как это сделать? Нужно запустить программу "fdisk" в каждой операционной системе. Это значит, что XENIX может общаться с разделом DOS, получая полное имя устройства, указывающее на другой раздел. Драйвер, который читает раздел DOS, должен знать, как выглядит DOS (т.е. знать файловую систему DOS). Если выполнить такую операцию, можно получать списки файлов и копировать их туда и обратно. К сожалению, DOS не имеет возможности чтения разделов XENIX.

При работе с гибким диском вы имеете дело только с одним разделом. Это снова ограничение DOS. Некоторые системы UNIX, в отличие от DOS, позволяют иметь столько разделов на жестком или гибком диске, сколько вы хотите, в отличие от DOS. По определению, гибкий диск DOS сформатирован в системе DOS, которая выполняет форматирование низкого уровня и помещает файловую систему DOS на гибкий диск. В системе XENIX гибкий диск может быть либо в формате файловой системы, либо неструктурированным устройством последовательного доступа подобно магнитной ленте. Для процедуры dosflp мы используем только гибкие диски в формате DOS.

Теперь к делу. Предположим, вы имеете систему DOS и файлы, находящиеся на диске DOS, вы можете читать и писать файлы на гибкий диск изXENIX. Но существуют некоторые ограничения на выполнение операции копирования, которые не слишком удобны пользователю. Например, вы можете сказать "doscp *.c a:". В результате все файлы текущего каталога которые оканчиваются на .c, будут скопированы на гибкий диск формата DOS наустройстве a:. Побочный эффект выполнения doscp заключается в том, что все символы перевода строки (или прогона строки) превращаются в символ возврат каретки/перевод строки, поскольку DOS обрабатывает конец строки иначе, чем XENIX. Таким же образом, когда вы копируете с гибкого диска формата DOS в XENIX, лишние символы возврата каретки убираются.

Что вы не можете сделать, так это сказать "doscp a:*.c". Команда doscp не допускает указания вида *.c при копировании с гибкого диска. Это происходит потому, что командный процессор распространяет метасимволы (*,?,[]) и не может непосредственно читать раздел DOS. Поэтому вы не можете использовать символы при копировании с гибкого диска DOS.

Отметим, что может наблюдаться гораздо больше побочных эффектов, когда вы имеете дело с гибкими дисками DOS. Во-первых, длина имени файла ограничена. DOS допускает до восьми символов имени файла плюс три символа расширения. В результате после копирования всех ваших файлов XENIX на гибкий диск многие из них могут иметь не те имена, которые они имели в XENIX. Это сущее страдание, когда вы пытаетесь сделать копию на гибкие диски DOS, потому что вы больше не имеете уверенности, как обращаться к файлам, когда вы копируете их обратно с гибкого диска. Кроме того, поскольку расширение имени файла в DOS имеет только три символа, файл с именем "spreadsheet.finance" может оказаться на гибком диске DOSс именем "spreadsh.fin" и распознавание его может представлять определенные трудности.

Но это еще не все. Когда файл копируется из XENIX в DOS, ВСЕ имена в DOS записываются заглавными буквами. Если у вас есть файлы с именами, в которых смешаны верхний и нижний регистры, то вы несколько потеряете понятность имен. Если вы используете в именах символы верхнего регистра при копировании файлов обратно в XENIX, они не переводятся на нижний регистр. В результате все имена ваших файлов оказываются записанными символами верхнего регистра в XENIX, что не очень удобно.

В чем мы нуждаемся, так это в таком средстве, которому мы можем указывать, какие файлы копировать с гибкого диска на жесткий диск, и которое копирует их с сохранением регистра в имени файла. Все это делает процедура dosflp.

Что делает dosflp?

Dosflp пытается исключить все негативные аспекты копирования файлов XENIX/DOS. Это высокое требование, но оно достижимо. Вкратце подход dosflp следующий: получить список имен файлов с гибкого диска, перевести имена в нижний регистр, выбрать из полного списка имена тех файлов, которые соответствуют вашим требованиям, и затем копировать файлы один за другим в текущий каталог XENIX. Для того, чтобы сделать это, требуется гораздо больше команд XENIX вида dosxx, а также различных других команд XENIX.

В дополнение к копированию, dosflp также выдает список файлов, которые имеются на гибком диске DOS, и удаляет файлы с гибкого диска. Эти функции легко реализовать, потому что как только один раз процедура доступа написана, добавить новые команды для выполнения операций над файлами довольно просто.

Обычно мы хотим управлять файлами определенного типа как группой. Сюда относятся ассемблерные исходные файлы, исходные файлы на языке C и файлы-заголовки на языке C. Поэтому, чтобы снять с вас обязанности по вводу универсальных символов для этих типов файлов, мы прямо указываем их в качестве опций команды dosflp. Например, ключ -a копирует только файлы, которые оканчиваются на .asm, поэтому нет необходимости помнить вид выражения для копирования этих файлов. Аналогично, ключ -c копирует все файлы, оканчивающиеся на .c, и ключ -h копирует файлы, оканчивающиеся на .h.

Как мы увидим позже, прямое указание, о котором мы говорим здесь, является выражением для команды grep. Использование всех возможностей команды grep достигается при указании образцов имен файлов.

Используйте ключ -d для указания, с какого гибкого диска производится копирование. По умолчанию это устройство a: или A:. Не имеет значения, на каком регистре вы укажете имя устройства. Для уверенности проверьте файл /etc/default/msdos. Этот файл содержит соответствия между символом устройства и маршрутным именем XENIX. Например, файл может выглядеть так:

       A=/dev/fd048ds9
       B=/dev/fd148ds9
       C=/dev/hd0d
       D=/dev/hd1d
       X=/dev/fd096ds15
       Y=/dev/fd196ds15

Как вы видите, маршрутные имена - это обычные имена устройств и ничего больше.

В качестве основного средства выполнения работы dosflp использует команду doscp. Это утилита способна понимать формат файловой системы DOS. Dosflp передает ей обозначение устройства и другие опции посредством переменных командного процессора. Например, ключ "-dB:" меняет устройство на B вместо принятого по умолчанию устройства A.

Если выражения прямого указания типа файлов не соответствуют тому, что вам нужно, вы можете определить свои собственные выражения сопоставления, используя ключ -e. Напомним, что выражение должно соответствовать синтаксису команды grep. Если вы хотите освежить свою память, посмотрите grep(1) в руководстве по AT&T UNIX или grep(C) в руководстве по XENIX. Для получения полной информации о синтаксисе посмотрите ed(1). Этот синтаксис является основой большинства команд, работающих с регулярными выражениями, таких как sed и grep.

Например, если вы используете выражение "*test*", выражение для grep должно иметь вид ".*test.*". Его можно слегка изменить в зависимости от того, что вы желаете иметь с каждой стороны цепочки test. В данном случае синтаксис указывает все символы (.*), за которыми следует цепочка t-e-s-t, а затем любая цепочка символов (.*). В этом случае ключ имел бы вид "-e.\*test.\*". Это кажется немного странным, но это соответствует синтаксису. (Двойные кавычки не являются частью команды.)Символ обратной косой черты (\) используется для экранирования звездочка. Если вы не экранируете ее, командный процессор соотнесет ее с именами всех файлов вашего текущего каталога, чего вы не желаете. Экранирование ее позволит, чтобы нужный символ был передан dosflp, для использования ее в grep-последовательности.

Ключ -h - это еще один из ключей прямого указания. Давайте вкратце рассмотрим его синтаксис внутри dosflp. Это ".*\.h$", и он указывает любой символ, за которым стоит одно или несколько вхождений любого символа (.*), литеральная точка (.\), символа h и вслед за ним конец строки (h$). Вы могли бы указать то же самое, используя ключ -e, но -h делает это гораздо легче. Ключ -l изменяет основное действие команды dosflp. Вместо копирования файлов он выдает список файлов. Это делается путем выполнения различных команд вида dosxx, в данном случае dosdir. Ключ выдачи списка полезен в dosflp, потому что вы можете получить список как информацию к решению о том, что делать дальше, и вам нет необходимости помнить команду dosdir.

Ключ -r также изменяет основную операцию команды dosflp. В этом случае файлы удаляются, а не копируются. Если вы указали этот ключ, выдается сообщение, которое просит вас подтвердить, что вы хотите удалить указанные файлы. Вы можете просто ответить "n", и запретить удаление, если вы ввели этот опцию случайно. Напомним, что удаленные файлы или файлы, включенные в список (в случае ключа -l), выбраны выражением grep, которое жестко запрограммировано или указано пользователем. По умолчанию выбираются ВСЕ файлы. Для ключа -r это соответствует тому, что сказать "rm *".

Последний ключ, -s, обеспечивает возможность доступа к файлам, которые размещены внутри подкаталога на гибком диске DOS. Если вы обращаетесь только к имени устройства, по умолчанию ключ -s относится к каталогу самого верхнего уровня на гибком диске. Если нужный вам файл находится в подкаталоге, вы должны использовать определенную нотацию, чтобы попасть в него. Одно из различий между XENIX и DOS заключается в символе, используемом для разделения элементов маршрутного имени. XENIX использует обычную запись в стиле UNIX - /x/y/z. В DOS применяется символ "обратная косая черта", т.е. \x\y\z. Но если вы хотите использовать команды XENIX на гибком диске DOS, вы должны применять обычную запись XENIX, a:/x/y/z. Это не совсем понятно, но правильно.

По умолчанию, dosflp копирует файлы с гибкого диска в ваш текущий каталог на жестком диске. Если вы измените операцию на выдачу списка или удаление, эта операция будет произведена на гибком диске.

ПРИМЕРЫ
       1. $ dosflp -dB: -c -l

Выдает список всех файлов вида *.c на гибком диске DOS, размещенном в устройстве B. В этом случае не происходит переход вниз в подкаталоги, а включаются лишь файлы, размещенные на верхнем уровне каталогов.

       2. $ cd /destdir
          $ dosflp -ssrc -e.\*src.\*

Переход в каталог, куда будут помещены файлы. Копируются файлы с гибкого диска DOS (устройство A, подкаталог src), в текущий каталог. Файлы для копирования указаны как *src*. В записи UNIX это выглядело бы так: "cp A:/src/*src* .".

       3. $ dosflp -r -stmp

Удаляет все файлы, размещенные в подкаталоге tmp на гибком диске DOS (устройство A). Обратите внимание, что сам каталог не удаляется. В записи UNIX это выглядело бы так: "rm A:/tmp/*".

       4. $ sh -x `path dosflp` -dB:

Запускает процедуру dosflp в отладочном режиме выполнения. Единственное ограничение при таком вызове командного процессора заключается в том, что файл данных, который вы посылаете ему (в данном случае dosflp), должен иметь полное маршрутное имя. Поскольку командный процессор НЕ выполняет поиск маршрутного имени файла, нам необходимо сперва найти маршрутное имя dosflp, затем передать его командному процессору, запущенному в отладочном режиме выполнения, а также передать процедуре dosflp аргумент в командной строке. Заметьте, что вызов dosflp таким путем не меняет значение переменной $#, которое только распознает ключ -dB: как аргумент.

ПОЯСНЕНИЯ

Строки 4-6 выполняют инициализацию по умолчанию путем сохранения значений в соответствующих переменных командного процессора. По умолчанию символ-шаблон ставится в соответствие всем файлам, указанным выражением для команды grep .\*. Обратная косая черта требуется для экранирования звездочки, поэтому она не перехватывается командным процессором. Устройство по умолчанию - A:. Операция по умолчанию - копировать файлы, что указано значением "c" для переменной опции.

В строках 8-25 устанавливаются значения ключей и производится проверка на наличие ошибок. Если командная строка имеет некоторые аргументы ($# -gt 0), мы перебираем каждый аргумент и проверяем его. Если найден допустимый ключ, переменные устанавливаются согласно ключу. Если обнаружен недопустимый ключ, выдается сообщение об ошибке и программа завершается с плохим статусом возврата.

Имеется два важных типа ключей. Ключи, которые выполняют прямое указание типа файла, просто устанавливают переменную EXP в соответствии с ключом. Аналогично, ключи, которые определяют, какой вид работы будет выполняться процедурой, просто устанавливают соответствующую переменную OP. Другие ключи должны обрабатываться путем извлечения одного или нескольких символов из командной строки, которые следуют за флагом ключа, эхо-отображения и конвейерной пересылки текущего аргумента ARG команде cut для извлечения символа (символов), начинающихся с третьего символа аргумента, затем присвоения результата этой операции соответствующей переменной.

Из всего сделанного следует вывод, что пробелы между ключами и символами, которые стоят за ними, не допускаются. Например, ключ -d должен получить имя устройства. По синтаксису должно быть -dB:, но не-d B:, потому что B: интерпретировалось бы как другой аргумент ARG вцикле for, а это все испортит.

В строках 27-39 операция, которая должна быть выполнена, определяется при помощи следующего оператора case. Если должно быть выполнено копирование, выдается сообщение "copying" и выполняется то, что следует за оператором case. Если должен быть выдан список файлов, выдается сообщение об устройстве, содержимое которого должно распечататься, затем выдается список файлов путем выполнения команды dosdir и конвейерной пересылки результата команде more, после чего dosflp завершается.

Если файлы должны быть удалены, пользователю выдается запрос на подтверждение удаления. Если ответ "yes", выдается сообщение, с какого устройства файлы будут удалены. Если ответ "no", dosflp завершается.

Остаток командного файла имеет дело с механизмом копирования. Строка 41 - это первый шаг в наведении моста над пропастью между двумя типами носителей. Команда dosls использована для получения полного списка файлов с гибкого диска. Перед тем как мы передадим этот список во временный файл, мы пропустим его через команду tr (translate), которая преобразует все символы на нижний регистр, чтобы при копировании файлов их имена были в нижнем регистре. В результате копии будут помещены на диск XENIX с именами файлов в нижнем регистре. Если у вас есть файлы с именами в верхнем регистре или в смеси регистров, вы должны вручную исправить их после копирования.

Строки 43-50 выполняют само копирование. Цикл for запускается для доступа к каждому файлу индивидуально. Это требование команд вида dosxx. Вы должны получать доступ к одному файлу один раз, поскольку этот уровень не обладает возможностью указания символа-шаблона. Имена файлов, которые использует цикл for, определены путем использования команды grep для выбора имен соответственно выражению, установленному ранее.

Имя каждого выбранного файла сначала отображается, так что пользователь может видеть, выполняется ли команда так, как ожидалось. В этом месте мы можем сделать одну из двух вещей: или копировать файлы, или удалить их. Эта операция определяется оператором case в строках 46-49.Если операция - копирование файлов, файлы копируются из комбинации устройство-файл в текущий каталог. Обратите внимание, что в переменную DRIVE включается подкаталог, если он был указан в командной строке. Это объясняет наличие символа "/" в конце присвоения значения переменной DRIVE в строке 16. Полное выражение должно быть таким: B:/subdir/file. Если операция - удаление файлов, комбинация устройство/файл удаляется выполнением команды dosrm. Попутно заметим, что маршрутное имя есть нечто гибкое (или небрежное, в зависимости от того, как вы смотрите на него) в том смысле, что вы можете сказать A:/subdir или A:subdir. Оба варианта правильны. После того как все файлы будут обработаны, временный файл удаляется.

ВОЗМОЖНЫЕ МОДИФИКАЦИИ КОМАНДНОГО ФАЙЛА

Одно из мест, где вы можете настраивать dosflp, это регулярные выражения. Уже включены выражения для .asm, .c и .h, но вы можете изменить это или добавить больше ключей для любой последовательности, которую вы часто используете.

3.3. Средства получения резервных копий

3.3.1. autobkp - автоматически наращивамый файл резервной копии

         Имя: autobkp

autobkp Автоматически наращиваемый файл резервной копии

НАЗНАЧЕНИЕ

Производит поиск по дереву файлов, которые изменялись за последние24 часа, и пересылает их в другую систему (посредством uucp) или перемещает их в другую область жесткого диска.

ФОРМАТ ВЫЗОВА
     autobkp [-c] [>logfile]

-c копирует файлы в другое место диска вместо использования uucp

ПРИМЕР ВЫЗОВА
     autobkp < filelist >> bkplog

Копирует все файлы, указанные в filelist, и записывает имена файлов в файл с именем bkplog

КОМАНДНЫЙ ФАЙЛ autobkp
    1   :
    2   # @(#) autobkp v1.0 Automatic file backup Author: Russ Sage
     
    4   if [ $# -gt 1 ]
    5     then  echo "autobkp: argument error"                     >&2
    6           echo "usage: autobkp [-c] [>logfile]" >&2
    7           exit
    8   fi
     
    10  if [ "$1" = "-c" ]
    11    then  COPY=on
    12    else  COPY=off
    13  fi
     
    15  echo "\nBACKUP DATE  `date  '+%a %m/%d/%y %H:%M:%S'`"
    16  echo "-----------------------------------------"
     
    18  SYSTEM=''     # destination system uucp node name
    19  :  ${SYSTEM:=`uuname -l`}
     
    21  echo "Sourse system:\t\t`uuname -l`\nDestination system:\t$SYSTEM"
     
    23  while read SRCDIR DESTDIR FILES
    24  do
    25        if [ ! -d $SRCDIR ]
    26          then  echo "autobkp: $SRCDIR is not a directory"
    27                continue
    28        fi
     
    30        cd $SRCDIR
    31        echo "\nFinding files in: $SRCDIR"
     
    33        for FILE in `find . -type f -ctime 0 -name "$FILES" -print`
    34        do
    35                  case $COPY in
    36                  off) uucp $FILE $SYSTEM!$DESTDIR;;
    37                  on)  cp $FILE $DESTDIR;;
    38                  esac
    39                  echo "  Transferred $FILE to $DESTDIR"
    40        done
    41  done
     
ПЕРЕМЕННЫЕ СРЕДЫ ВЫПОЛНЕНИЯ
COPY Флаг, определяющий, используется команда uucp или cp
FILE Имя каждого файла, найденного в исходном списке маршрутов
FILES Символ-шаблон, указывающий, какие файлы определены
PATH1 Имя маршрута-источника
PATH2 Имя маршрута-приемника
SYSTEM Имя системы-приемника для uucp
ОПИСАНИЕ

Зачем нам нужен autobkp?

Как мы заметили, файлы в UNIX плодятся как кролики. Чем больше файлов мы создаем, тем сильнее желание сохранять их упорядоченными. Довольно легко стать ленивым или получить ложное представление о безопасности и пренебречь регулярным копированием.

Вы можете подходить к копированию файлов несколькими путями. Наиболее популярной стратегией является выполнение наращиваемого копирования, когда вся система копируется с некоторой начальной даты (и иногда повторно с регулярными интервалами, но не часто). При коротких интервалах (обычно ежедневно) файловая система проверяется на наличие файлов, которые были модифицированы или добавлены за последние 24 часа. Такие файлы копируются, поэтому копия в целом поддерживается такой, какой является система в настоящее время.

Где размещать копируемые файлы - это еще один интересный вопрос, зависящий от конфигурации вашей системы, количества доступного пространства и важности данных. Давайте рассмотрим некоторые возможности.

Автономная микро- или супермикросистема может иметь всего один жесткий диск. Если диск содержит достаточно места для размещения другого раздела, вы можете копировать в этот раздел. Раздел может также использоваться как неструктурированное устройство в отличие от файловой системы и рассматриваться как магнитная лента или гибкий диск. Среди других возможностей хранения информации могут быть второй жесткий диск, кассетная лента или устройство копирования на ленту. Если вам недоступна ни одна из этих возможностей, вы всегда можете копировать на гибкие диски. Это утомительная ручная работа, но она может быть выполнена при помощи команд tar или cpio.

Если вы также имеете доступ к другой, большей системе, такой как общий главный компьютер, вы можете копировать файлы, посылая их в эту систему посредством команды uucp. Даже если вы имеете достаточно места в вашей собственной системе для сохранения ваших копий, у вас может быть очень сильное желание послать копии всех важных файлов в главную машину, потому что это даст вам выносную копию за пределами вашего места расположения.

Нам необходим механизм, который обычно запускается автоматически(по команде cron или с помощью процедуры at, описанной в главе 5). Сначала он обнаруживает все файлы, которые были изменены в последние 24часа (надеемся, что вы уже имеете первоначальную копию всего). Он начинает искать файлы из указанных каталогов и копировать подходящие файлы в указанные каталоги-приемники. Он копирует файлы, используя утилиты, которые наилучшим образом соответствуют используемой вами конфигурации.Все эти вещи выполняются нашим командным файлом autobkp.

Что делает autobkp?

Вы перечисляете маршруты и autobkp находит файлы по этим маршрутами копирует их в то место, которое вы указали. Вы можете указывать имена файлов по образцам, таким как *.c, *.h или каким-либо еще. С помощью autobkp вы можете копировать важные файлы без копирования всех файлов. Иногда это удобно - пропускать файлы при копировании. Типичные файлы, которые вы, возможно, не хотите копировать, - это очень большие файлы(не являющиеся важными, как файл core и файлы данных), временные файлы(как *.o, которые вновь создаются при каждой новой компиляции) и исполняемые файлы, если у вас есть исходные программы на языке Си и вы можете их скомпилировать для получения новых исполняемых файлов. Пропуская эти файлы, вы можете уменьшить размер ваших копий на мегабайты.

По умолчанию копирование производится командой uucp, которая предполагает, что у вас подчиненная система по отношению к главной машине и копирует ваши файлы в большую систему. Если вы хотите копировать ваши файлы в другое место жесткого диска или на другой жесткий диск, используйте ключ -c для копирования командой cp вместо использования команды uucp. Во время процесса копирования на стандартный вывод выводятся сообщения о состоянии дел. Это позволяет легко собрать все сообщения путем переадресации stdout на время копирования. Если вы выполняете autobkp в ручную, сообщения выводятся на экран. Первое сообщение - это заголовок, который печатает день, дату и время. Это выглядит так:

     |  BACKUP DATE   Fri 05/23/86 17:33:35
     |

Второе сообщение определяет систему-источник и систему-приемник. Оно появляется ниже. В нашем примере система-источник - russ, а система-приемник - vax.

     |  Source system:   russ
     |  Destination system:  vax

При каждом входе в систему-источник выдается следующее сообщение:

     |  Finding files in: src_dir
     |

где выражение src_dir - это место, откуда файлы будут переданы в цикл копирования. Обратите внимание, что первое имя должно быть именем каталога, потому что autobkp начинает именно с этого места поиск файлов. Если первое имя не является каталогом, программа печатает сообщение об ошибке и продолжает работу со следующим набором источник/приемник для копирования.

Для каждого найденного файла печатается следующее сообщение после завершения копирования:

     |  Transferred  file  to dest_dir
     |

которое указывает, что файл file был скопирован в каталог-приемник с именем dest_dir.

ФАЙЛ СО СПИСКОМ МАРШРУТОВ

Чтобы сделать интерфейс настолько гибким, насколько это возможно, autobkp читает стандартный ввод. Переназначая stdin, вы можете поддерживать разные списки файлов, которые необходимо копировать и переключать их в командной строке. Вы можете иметь один список маршрутов для системных файлов, другой для исходных файлов, третий для личных файлов, четвертый для файлов с готовым продуктом и так далее. Для каждой из этих групп файлов создается список маршрутов и передается в качестве входа для autobkp. Входные данные читаются как три поля: FROM, TO иTYPE. Поле FROM - это каталог-источник. Поиск файлов начинается с этого места. Напомним, что autobkp проходит вниз до конца дерева файлов, начиная с указанного каталога.

Поле TO - это каталог-приемник, куда все файлы, найденные для данной записи в файле со списком маршрутов, помещаются на машине-приемнике или в разделе-приемнике.

Поле TYPE - это описатель-шаблон, который сообщает autobkp, какие файлы искать. Его значение может быть *, *.c, *src*, и так далее. Как мы увидим позже, этот описатель передается команде find Unix, которая фактически и выполняет поиск файлов. Вы можете использовать любое выражение в поле TYPE, если оно соответствует синтаксису find.

Итак: все файлы, которые были изменены в последние 24 часа, обнаруживаются в списке FROM с помощью описателя TYPE и копируются в область TO.

Ниже приводится типичный файл со списком маршрутов. Он указывает несколько каталогов, в которых производится поиск файлов. Обратите внимание, что эти каталоги находятся под регистрационным каталогом: если вы хотите скопировать ВЕСЬ регистрационный каталог полностью, вы можете указать этот каталог, но здесь мы хотим выбрать только указанные каталоги.

     /usr/russ/bin    /pack1/russ/.bkp/bin       *
     /usr/russ/doc    /pack1/russ/.bkp/doc       *
     /usr/russ/src    /pack1/russ/.bkp/src       *.c
     /usr/product1    /pack1/russ/.bkp/product1  *.[ch]

Эти строки копируют каталоги bin, doc и src на локальной машине автора. В случае каталога src мы указали, что копировать нужно только исходные файлы на языке Си. Будет также скопирована некоторая полезная информация из другого места этой же системы. Будут скопированы только файлы с расширением *.c и *.h.

Место назначения (прямо указанное в командном файле автоматического копирования) - другая система UNIX. Место назначения - некоторый смонтированный диск, регистрационный каталог, подкаталог копий (bkp).

ИСПОЛЬЗОВАНИЕ cron

Теперь, когда процедура autobkp знает, что искать, давайте скажем ей, когда искать. Cron, вечный резидентный хранитель времени, может легко выполнить эту работу. Входные данные для cron обычно устанавливаются системным администратором (или кем-либо, кто имеет права записи в/usr/lib/crontab), так что вы должны попросить администратора установить для вас вход в файл данных cron. Для получения дополнительной информации о входных данных cron, прочтите cron(1M) в Руководстве администратора. Коротко говоря, полями в файле /usr/lib/crontab являются минута, час, день месяца, месяц и день недели. Используя *, мы можем установить принудительно многие из этих полей во все возможные значения. Входные данные для cron, копирующие мой регистрационный каталог в4.00 утра каждый день каждой недели каждого месяца года, выглядят так:

0 4 * * * /usr/russ/bin/autobkp.cron Обратите внимание, что вход в cron вызывает управляющую процедуру вместо того, чтобы непосредственно использовать autobkp. Имеется несколько важных причин, чтобы написать процедуру на базе утилиты autobkp. Во-первых, cron не печатает диагностическую информацию на ваштерминал, поэтому если что-нибудь идет не так, вы никогда об этом не узнаете. Во-вторых, проще поддерживать усеченную версию autobkp, а звуковые предупреждения добавлять в управляющую процедуру. Вы можете сделать собственные модификации управляющей программы и не беспокоиться об отсутствии сообщений от самой утилиты. Управляющую программу можно настолько усложнить, насколько вы желаете. Представленная здесь вполне работоспособна, но легко может быть дополнена.

     # Cron-driven autobkp driver
     echo "backed up: `date`" > /dev/tty00
     /usr/bin/autobkp < /usr/russ/bin/autobkpath
                      >> /usr/russ/bin/autobkp.log

Этот драйвер выдает сообщение на терминал, запускает autobkp, использует для ввода файл со списком маршрутов в каталоге bin и помещает все выводные сообщения в файл протокола. Отметим, что имя терминала дано как абсолютное (tty00). Это правильно только в том случае, когда в вашей системе имеется такой терминал. Использование этого имени терминала позволяет сообщению появиться на экране даже если никто на нем не зарегистрирован. Это хорошо, потому что первое, что вы сможете увидеть утром на вашем экране - это сообщение. Если у вас нет указанного терминала, вы можете сделать что-то другое, например, передачу самому себе почтового сообщения.

ПРИМЕРЫ
       1. $ autobkp

Запускает программу без передачи ей файла со списком маршрутов и без файла протокола. Поскольку поля FROM, TO, TYPE ищутся в стандартном вводе, введите их вручную. Когда вы нажмете возврат каретки, autobkp выполнит указанные действия, напечатает информацию на экран терминала и будет ожидать дальнейшего ввода. Для завершения выполнения командного файла введите ^d (в результате оператор read вернется с ненулевым статусом).

       2. $ autobkp < pathlist

Получает все входные данные из файла со списком маршрутов, но печатает всю протокольную информацию на экран терминала. Autobkp завершается, когда прочитает все данные в файле pathlist.

       3.  $ autobkp >> logfile

Как и в первом случае, списки маршрутов должны быть введены с клавиатуры. Все выходные данные выводятся в файл протокола, а не на экран. Для завершения autobkp введите ^d.

      4. $ autobkp -c < pathlist >> logfile

Копирует файлы из одной области жесткого диска в другую (определенную каталогом-приемником в файле pathlist). Берет все входные данные из файла pathlist и выводит все выходные данные в файл logfile.

ПОЯСНЕНИЯ

Строки 4-8 выполняют проверку на наличие ошибок. Autobkp може тбыть вызван либо без указания опций, либо с одной опцией (-c, при использовании cp). Вспомните, что переназначение ввода-вывода НЕ принимается во внимание при рассмотрении аргументов, потому что командный процессор интерпретирует символы переназначения и то, что следует за ними, до вызова команды. Таким образом, если количество позиционных параметров больше одного (#1 -gt 1), получаем ошибочное условие. Затем выдается сообщение об ошибке и синтаксическая подсказка и программа завершается.

В строках 10-13 проверяется использование ключа -c. Обратите внимание, что мы не проверяем, равен ли параметр $# единице и не пытаемся выделить первый символ, чтобы посмотреть, равен ли он "-". Это потому, что такая проверка приведет к ошибке, если не указан никакой ключ (что является верным синтаксисом, как указывалось ранее).

Если мы сказали

      if [ $1 = -c ]

и не указали ключей, то команда проверки не сработает и будет выдано сообщение о том, что "no argument in the statement" ("в операторе нет аргументов"). Но если мы выполним экранирование, например, так:

      if [ "$1" = "-c" ]

то кавычки допускают нулевое значение аргумента, так что проверка правильно оценит недостающее значение $1 как "равен ли нуль -c?" Это даст результат "ложь", поэтому все хорошо.

Попутно давайте внимательно рассмотрим работу команды проверки. Вы можете выполнить проверку значения двумя способами. Первый - сравнение строк, а второй - числовое сравнение. Переменные командного процессора ВСЕГДА хранятся в виде строк. Вы можете, тем не менее, заставить систему рассматривать эти последовательности как числа и интерпретировать их значения как числовые, подобно оператору number = val(STRING$) языка Бейсик. Вы можете сказать системе, чтобы она изменила свой способ рассмотрения символьных строк путем изменения синтаксиса операции сравнения. Для символьных строк сравнение выглядит так:

        str1 = str2

а числовое сравнение выглядит так:

        num1 -eq num2
             -lt
             -gt

Сверьте это с руководством. Если вы попытаетесь смешать символьное сравнение с числовым, сравнение не будет работать. У меня забрало много месяцев программирование на командном процессоре, пока наконец я заметил это незначительное различие. Если не рассматривать подробно что-либо подобное, то такие технические ошибки кажутся неуловимыми, но можно найти объяснения, почему что-нибудь работает не так.

Вернемся к возможности проверки кода. Если был передан ключ -c, переменная COPY устанавливается, что значит "Да, мы собираемся копировать командой cp, а не использовать uucp". Если ключ -c не используется, переменная COPY не устанавливается.

В строках 15-16 печатается заголовочное сообщение о том, что будет выполняться копирование. Обратите внимание, что мы спрятали команду date системы UNIX внутри оператора echo, сократив число перехваченных данных, которые мы должны иметь, чтобы получить дату непосредственно.

Проследите за кавычками в этом операторе. Внешние кавычки являются двойными для того, чтобы упаковать весь аргумент для оператора echo. Знаки ударения (`) обрамляют команду date так, что она является "выполняемой внутри" и ее выходное сообщение перехватывается для наших нужд. Одинарные кавычки внутри команды date используются для передачи формата, который изменяет внешний вид значений так, чтобы заголовок выглядел более красиво. В конце оператора echo кавычки следуют одна за другой.Это не представляет проблемы, поскольку во вложенности нет никакой двусмысленности. Вы должны помнить, что нужно следить за ситуацией, когда вы и командный процессор можете расходиться во мнениях, т. е., когда вы должны обращаться к записи вида "\".

В строке 18 переменной SYSTEM присваивается имя удаленной системы, в которую вы будете копировать командой uucp. Здесь она равна нулю, что позже вызовет выполнение другой операции для обеспечения функционирования по умолчанию. Если же вы хотите всегда копировать на вполне определенную систему, модифицируйте эту строку, чтобы назначить имя этой системы. Если оставить строку 18 так, чтобы она назначала ноль, строка14 поймает это значение и присвоит переменной SYSTEM имя вашей текущей системы. Другими словами, если вы оставите строку 18 так, как она есть, и вызовете autobkp без ключа -c, вы будете копировать командой uucp сами на себя, что вполне допустимо. Однако, из соображений эффективности вы, вероятно хотели бы выполнить autobkp -c для получения локальной копии.

Строка 19 иллюстрирует концепцию, часто используемую при программировании на командном языке. Давайте вкратце рассмотрим ее.

Первый символ - это ":". В данном случае мы интересуемся, что происходит при проверке, а не возвращаемым значением, поэтому мы заставили холостую команду ("не делать ничего") получать результат как аргумент. Текст, следующий за двоеточием, интерпретируется так: "Если переменная SYSTEM не установлена или установлена в ноль, присвоить ей значение, которое следует за ней". В данном случае значение - это выход команды uuname -l. Эта команда устанавливает, что система-приемник является той же системой, что и исходная, если система-приемник не была прямо указана ранее.

Мы используем uuname -l, а не стандартное выражение uname -n по причине совместимости. Uname -n правильно получает имя узла из структуры uts ядра операционной системы, но не все системы XENIX используют элемент узла в виде структуры uts ядра системы. Вместо этого они посылают имя в файл /etc/systemid, который соответствует микросети(micnet), разработанной для XENIX фирмой Microsoft. Команда uuname -l это локальное имя (или исходная машина) для системы uucp. Эта команда возвращает правильное значение и в UNIX, и в XENIX. Имеет смысл использовать то, что всегда работает!

Строка 21 печатает имя исходной системы и системы-приемника. Это сообщение добавляет информацию в запись о том, что собирается делать autobkp, поэтому вы можете видеть по выходным данным, как вы установили данный командный файл. Снова мы спрятали команду uuname внутри оператора echo. У нас нет необходимости сохранять имя исходной системы, поскольку оно нам всегда доступно при помощи команды uuname. Поскольку мы всего два раза используем это имя, то решили не использовать для него какую-либо переменную.

Строки 23-41 - это полный цикл, который управляет автоматическим копированием. Управляющим циклом является оператор while, который читает значения из стандартного ввода. Заметьте, что вы можете считать несколько значений в операторе read. Это удобно, если вы хотите читать более одного значения, но не должны выделять каждую порцию входных данных для того, чтобы определить, является это первым, вторым или третьим элементом данных. Мы читаем их все сразу и они присваиваются указанным переменным. Поскольку выполняется чтение стандартного ввода, мы можем перенаправить stdin при вызове autobkp и оператор read никогда не узнает, чем они отличаются. Если мы не переназначаем входные данные, мы должны вводить их с клавиатуры. Цикл завершается при чтении конца файла- в данном случае конец файла со списком маршрутов или символа control-d (^d) с клавиатуры. Поэтому управляющий цикл работает так: "пока еще есть данные для чтения, читать их, обрабатывать, затем читать следующие."

Строки 25-28 проверяют, является ли каталог-источник действительно каталогом. Если нет, выдается сообщение об ошибке и оператор continue приводит к следующей итерации цикла while.

В строке 30 производится смена каталога на каталог-источник. Вотпочему выходные данные команды find являются относительными к точке (.). Если бы мы не выполнили команду cd, то полное имя стало бы абсолютным, что могло бы отразиться на системе-приемнике. Тогда маршрут, начинающийся с каталога-приемника, имел бы вниз от себя лишний абсолютный путь.

Строка 31 печатает каталог, в котором ищутся исходные файлы. Хорошо иметь их в файле протокола, поскольку вам легче будет читать и следить, где в данный момент работает autobkp.

Строки 33-40 выполняют непосредственно копирование файлов. Здесь циклом является цикл for, который читает имена файлов из выхода команды find. Заметьте, что это автоматически ограничивает общее число файлов, которые может обрабатывать цикл. Этот факт ранее был объяснен в этой книге, но давайте рассмотрим его еще раз. Если find выдает список, состоящий из сотен файлов, то список слов оператора for переполняется и нарушает работу вашего командного процессора (или по крайней мере команды find). Здесь принято допущение, что вы не хотите иметь так много файлов в исходном каталоге. Вы можете избежать этого, разбивая исходный каталог на более мелкие части и пересылая их в файл pathlist. Если вы хотите создать действительно хороший цикл, измените его, например, так:

      find . -type f -ctime 0 -name "$FILES" -print | while read FILE

Благодаря использованию такого цикла, число имен файлов теперь можно изменить от входных ограничений для командного процессора до размеров канала системы (который очень большой, практически неограниченный). Изменение этой одной строки не оказывает влияния на другие части цикла.

Давайте рассмотрим детально команду find. Во-первых, мы указали ей поиск файлов в текущем каталоге (.). Это делает все полные имена относительными по отношению к точке. Затем мы сказали команде find найти все файлы типа f, что означает обычные файлы, а не каталоги или файлы устройств. Мы не хотим копировать такие файлы. Дальше мы говорим ей найти файлы, которые были изменены. Под "изменением" мы подразумеваем доступ или модификацию. (Посмотрите в описании stat(2), какие команды изменяют доступ, изменяют и модифицируют время. Говоря "делать поиск для нахождения "ctime 0"", мы имеем в виду все файлы, измененные за последние 24 часа. Объяснения, которые документация по find дает по поводу этих чисел, довольно непонятны, поэтому отнеситесь к ним с недоверием.) Затем мы говорим команде find "найти только те файлы, которые определены путем соответствия их имен маршрутным именам, указанным в переменной $FILES, значение которой мы читаем". В этом месте мы можем отфильтровать файлы, которые нам не нужны (как объяснялось предварительно) или выбрать файлы, которые нам нужны. В конце мы говорим команде find "напечатать имена всех файлов, которые соответствуют перечисленным критериям". Затем имена файлов передаются в цикл for. Другими словами, выходные данные команды find становятся аргументом для охватывающего цикла for.

В строках 35-38 оператор case определяет, какого рода копирование мы собираемся делать, и запускает команды копирования. Если переменная COPY не установлена, мы копируем файлы командой uucp. Обратите внимание, что местом назначения является SYSTEM. Если мы оставили SYSTEM в нуле в строке 18, то SYSTEM - это наша собственная система и мы копируем командой uucp файлы к себе. Если COPY установлена, то независимо от значения SYSTEM мы копируем (но не командой uucp) файлы в другой каталог текущей системы. Этот каталог может быть на том же жестком диске или в другой смонтированной файловой системе. После того, как файл скопирован, выдается сообщение, которое говорит о том, какой файл и куда был передан. Удобно иметь в файле протокола эту информацию, поскольку мы имеем возможность проследить, куда были пересланы ваши скопированные файлы.

Цикл find выполняется до тех пор, пока не скопируются все файлы в текущем сегменте дерева. Напомним, что команда find рекурсивная, поэтому убедитесь, что вы указывали не больше деревьев, чем вы хотели. Если вы указали "копировать, начиная с корня (/)", то может быть передан каждый файл, имеющийся в системе. Когда цикл for выполнился, внешний цикл while идет к следующей итерации. Когда все входные данные обработаны, программа завершается.

НЕКОТОРЫЕ ОСОБЕННОСТИ uucp

Когда используется uucp, в маршруте приемника должен быть установлен бит разрешения выполнения ("x") для группы "others" (остальные) для всех промежуточных каталогов, ведущих к файлу. Это будет выглядеть так:

         --------x

Самый последний каталог должен иметь права доступа вида "wx", чтобы uucp могла писать файл в каталог. После этого владельцем файла считается uucp. Если собственником файла хотите быть вы, скопируйте его (используя cp, а не mv) с другим именем и он будет вашей собственностью. Если вы переименуете его командой mv, вы только измените имя, связанное с тем же индексным описателем файла (inode). Но если вы скопируете его командой cp, вы создадите новый отмеченный описатель файла. Этот новый описатель файла (созданный вами) имеет ваши идентификатор пользователя (uid) и идентификатор группы (gid), поэтому вы владеете им. Если вы находитесь в корне системы и копируете файл (используя cp, а не mv) поверх другого существующего файла, информация в описателе файла не изменяется, а меняются только данные, доступ к которым указывает описатель файла.

Когда uucp устанавливает предшествующие права доступа к файлу на всех промежуточных каталогах такими, что все имеют право записи, последний каталог НЕ будет иметь защиты. Предоставление любому пользователю права записи означает, что кто угодно может удалить или изменить файлы в этом каталоге. Не каждый хочет давать всем это право. Если же вы копируете файлы в обычную область команды uucp общего доступа (/usr/spool/uucppublic/$LOGNAME), то вы должны внимательно следить за ними. Многие системы имеют запускаемые с помощью cron программы, производящие в данном каталоге поиск файлов, к которым не было доступа в течение определенного количества дней, и удаляют такие файлы - это вредит вашим копиям. Если период хранения больше, чем промежуток между вашим копированием, у вас может быть все в порядке. Как и многое другое, это зависит от ваших обстоятельств и требований безопасности.

УСОВЕРШЕНСТВОВАНИЯ

В оригинале файл со списком маршрутов имеет аргумент TYPE в конце аргумента FROM, например /usr/russ/bin/*. Это представляет проблему (кроме того, что показывает, что ваш автор еще не является мастером!), потому что когда символ * будет выделен, он будет расширен в имена всех файлов вместо того, чтобы трактоваться как литеральный символ. Простое решение - использовать отдельные поля, что и было сделано. Мастерским решением является экранировать метасимвол для сохранения его как литерального символа. Как только символ * будет выделен из маршрутного имени, символ \ представит его в виде * вместо того, чтобы дать его на расширение. Например, можно написать так:

TYPE=`basename \"$FROM"` Здесь символ * присваивается переменной TYPE, вместо того, чтобы присвоить TYPE список всех файлов, которые соответствуют метасимволу. Затем, когда будет вызвана команда find, переменная TYPE должна быть экранирована так, чтобы метасимвол интерпретировался не командным процессором, а самой командой find.

Назад | Содержание | Вперед