ПОЯСНЕНИЯ
Строка 4 устанавливает место "мусорной корзины" так, чтобы она размещалась в вашем регистрационном каталоге под именем .trashcan. Заметьте, что ее именование, начиная с точки, делает ее не распечатываемым, или скрытым файлом. Единственный способ увидеть такие файлы использовать ключ -a в команде ls.
Строки 6-8 проверяют, определен ли сейчас каталог "мусорной корзины". Если нет, он создается. Обратите внимание, что поскольку его создаете вы, он имеет такие права доступа на чтение и запись, как в вашем регистрационном каталоге. Строки 10-21 проверяют, начинается ли первый позиционный параметр с черточки (-). Если такой параметр обнаружен, проверяется, является ли он ключом командного файла can (-l, -r, -z или -?). Обратите внимание, что для того, чтобы для использования двойных кавычек внутри двойных кавычек (строка 10), вы должны экранировать кавычки. Символ обратной косой черты (\) использован именно для этой цели.
Если указан ключ -l, выдается напоминание об имени каталога "мусорной корзины", команда ls выводит список файлов в "мусорной корзине" и процедура can завершается, поскольку требовалось только вывести список.
Если указан ключ -r, выдается сообщение об имени каталога очищаемой "мусорной корзины" и файлы в ней удаляются командой rm. Это разрушительная вещь и удаляет ваши файлы навсегда. После удаления can завершает работу. Вы можете дополнить программу процедуры так, чтобы давать подтверждение перед выполнением команды, если это позволит вам чувствовать себя более спокойно.
Если указан ключ -z или -?, выдается подсказка об использовании и can завершается. Это не совсем хорошо, но мы не можем использовать символ *, соответствующий любому другому ключу, поскольку ключ может быть предназначен для команды mv, а не для can. Благодаря использованию всего двух аргументов для обработки ошибок, мы можем разрешить передачу всех остальных аргументов. Если ключ не является одним из ключей can, или одним из указанных ключей обработки ошибок, то он передается команде mv. Если ключ недопустим для этой команды, команда mv выдает свое сообщение об ошибке и завершает работу. Вы можете, естественно, модифицировать командный файл так, чтобы он проверял допустимость ключей команды mv на "внешнем" уровне. Тогда он может выдать сообщение об ошибке и завершиться, если указанный ключ недопустим ни для can, ни для mv. Вопрос в том, стоит ли платить за более полный контроль над обработкой ошибок ценой разбухания программы и временем исполнения. Строка 23 выполняет собственно перемещение файлов в "мусорную корзину". Заметьте, что это выполняется только если не указаны никакие ключи can, поскольку это поведение can, принятое по умолчанию. Здесь используется параметр $@. Путем включения всех параметров в командную строку, любые ключи, предназначенные команде mv, передаются ей. Таким способом мы можем изменить путь, которым файлы посылаются в "мусорную корзину".
Строки 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. Оба варианта правильны. После того как все файлы будут обработаны, временный файл удаляется.
Строки 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$) языка Бейсик. Вы можете сказать системе, чтобы она изменила свой способ рассмотрения символьных строк путем изменения синтаксиса операции сравнения. Для символьных строк сравнение выглядит так: