Мои статьи



Структура разделов [lefttabs] и [righttabs]

Эти разделы файла конфигурации Total Commander содержат информацию о текущем состоянии вкладок на левой [lefttabs] и правой [righttabs] панелях. Прежде всего, следует отметить, что выражение "текущее состояние" не совсем верно. Попробуйте в произвольный момент открыть файл wincmd.ini и просмотреть эти разделы - вы убедитесь, что они отражают состояние вкладок не на данный момент, а, скорее всего, на момент начала сеанса работы. Чтобы синхронизировать эти разделы, необходимо выдать команду cm_ConfigSaveSettings.

Прежде всего, двигаясь от общего к частному, рассмотрим наиболее распространенный случай, когда открыто множество вкладок. Вот один из примеров раздела [lefttabs], а именно - содержание файла XXcopy.tab, который я в целях наглядности несколько подправил. Здесь и далее рассматривается левая панель, для правой аналогично.

[lefttabs]
0_path=c:\utils\XXcopy\
0_options=1|0|0|0|0|1|0
1_path=c:\user\HTML\Статьи\XXcopy\
1_caption=Статьи\XXcopy
1_options=1|0|0|0|0|1|0
2_path=c:\Utils\Test\
2_options=13|0|0|0|0|0|0
3_path=c:\user\Batches\
3_options=1|0|0|0|0|2|0
4_path=c:\Utils\
4_options=5|0|0|0|0|0|0
5_path=\\\Registry\HKEY_USERS\
5_options=1|0|0|0|0|0|0
6_path=::
6_caption=Desktop
6_options=1|0|0|0|0|0|0
7_path=D:\Documents and Settings\
7_options=1|0|0|0|0|0|0
8_path=c:\Utils\Test\
8_options=1|3|1|0|0|0|0
activetab=4

На первый взгляд, все очевидно. Вкладки нумеруются слева направо, первый индекс 0. У каждой вкладки два обязательных ключа: <номер>_path и <номер>_options и один необязательный - <номер>_caption, содержащий заголовок (название) вкладки, присвоенное пользователем.

Начнем с ключа <номер>_options. Подробное изучение смысла, который вкладывается в цифры, не проводилось, однако удалось сделать некоторые наблюдения.

Первая цифра - вид, используемый для представления файлов. Например, 0 - brief, 1 - full, 4 - show comments и т. д. Номер 13 в ключе 2_options соответствует одному из content-плагинов, идущим в моем списке под №8. Третья цифра с конца показывает, находится ли текущая директория внутри архива, предыдущая - тип архива, и т. д.

Для меня при написании скрипта TabTools была наиболее важна предпоследняя цифра, которая может принимать значения 0, 1 или 2, что соответствует состоянию "запертости" вкладки - "unlock", "lock" и "lock, but directory changes allowed" соответственно.

Обратим внимание, что кавычки не используются даже в тех строках, что содержат пробелы (например, 7_path=D:\Documents and Settings\). Символ :: означает рабочий стол. Ключ 5_path=\\\Registry\HKEY_USERS\ - FS-плагин TurboRegistry.

Казалось бы, все просто. Ключ activetab=4 тоже вроде бы сомнений не вызывает. А вот теперь вопрос на засыпку: какая директория является текущей? Вы думаете, c:\Utils\? А вот и нет! Не существует никакой связи между цифрами 4 в ключах activetab и 4_path. Точнее, отдаленная связь есть - текущая вкладка располагается рядом с c:\Utils\, но в общем случае отображает другой путь и другие опции!

Аналогично, пытаясь ответить на вопрос "Сколько вкладок открыто на левой панели?", вы скажете "Девять" и опять ошибетесь - десять.

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

Дело в том, что информация о текущем пути и опциях всегда хранится не в разделах [lefttabs] и [righttabs], а [left] и [right]. Типовое содержание раздела [left]:

[left]
path=d:\Winnt\
ShowAllDetails=1
show=1
negative Sortorder=1
SpecialView=0
sortorder=3

Тут все еще проще и в пояснениях не нуждается. При этом заголовок панели, если он есть, все равно располагается в разделе [lefttabs], в ключе activecaption, и в этом есть смысл.

Теперь рассмотрим некоторые особые, частные случаи.

Прежде всего загляните в свои настройки, раздел "Folder Tabs", флаг "Show tab header also when there is only one tab". Не знаю как вы, а я не вижу в установке этого флага решительно никакого смысла. Впрочем, если этот флаг все-таки стоит, придется рассмотреть один частный случай вместо двух.

Итак, предполагая, что флаг сброшен, закроем все вкладки (например, с помощью моего скрипта CloseAllTabs) и вернем панель к первозданному виду, характерному для менее продвинутых файл-менеджеров или для самого ТС версии ниже 6.

Сохранив настройки и открыв файл конфигурации, мы увидим, что раздел [lefttabs] отсутствует - ровно до тех пор, пока мы не создадим вкладку - тогда их сразу будет две. Однако в разделе [lefttabs], напомним, будет содержаться информация всего об одной из них - той, которая не является активной.

Можно ли добиться, чтобы при единственной вкладке раздел [lefttabs] существовал? Как я узнал при написании скрипта TabTools - можно. В реальной жизни такая ситуация вряд ли встретится, но хорошая программа должна предусматривать все, даже маловероятные, возможности.

Создадим две вкладки, одну из них запрем, а вторую закроем. На панели останется одна запертая вкладка. Тогда раздел будет иметь вид:

[lefttabs]
activetab=0
activelocked=1

Единственное, что может здесь меняться - значение ключа activelocked: 1 - "lock" или 2 - "lock, but directory changes allowed". Стоит нам отпереть вкладку, она пропадет (если флаг сброшен) или, в противном случае, присвоит ключу activelocked значение 0.

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

Напоследок приведу информацию для программистов - путь к текущей директории на левой панели можно получить и без чтения раздела [left], а запросив текст дочернего окна №3 класса TMyPanel.


К вопросу об анатомии окна Multi-Rename Tool и раздела [rename]

Инструмент группового переименования - один из мощнейших вспомогательных инструментов, встроенных в Total Commander. Помимо задания различных опций переименования, предоставляется возможность сохранять набор сложных настроек в виде именованных шаблонов и загружать их при необходимости. Эти шаблоны хранятся в разделе [rename] файла конфигурации wincmd.ini. Ниже будут рассмотрены ключи этого раздела и их связь с окном Multi-Rename Tool.

[rename]
Шаблон_name="[C]"
Шаблон_ext="[E]"
Шаблон_search="аб"
Шаблон_replace="вг"
Шаблон_params=0|999|-1|3|1|1

Рассмотрим, как сохраняется шаблон в разделе [rename]. Здесь "Шаблон" - произвольное имя. Ключей всегда пять. И если с ключами _name, _ext, _search и _replace все ясно, то на _params следует остановиться подробнее.

Значение ключа - от четырех до шести целых чисел, разделенных символом "|". Если крайнее справа поле равно "0", оно отбрасывается. Значение полей ключа _params рассматриваются в следующей таблице и соотносятся с позициями, обозначенными красным на скриншоте:

Позиция Смысл Значения Комментарий
1 Регистр имени 0...4 Раскрывающийся список содержит 5 режимов регистра. Первому режиму "Unchanged" соответствует значение поля 0, второму - 1, и т. д.
2 Начальное значение счетчика любое
3 Приращение счетчика любое
4 Число разрядов счетчика 1...10
5 Использование регулярных выражений 0 или 1 "1" - режим включен, "0" - выключен
6 Замена 0 или 1 "1" - режим включен, "0" - выключен

Позиция Индекс
(версия 7.0 / 7.5)
Класс
2 29 TEdit
3 28 TEdit
7 18 / 19 TComboBox / TMyComboBox
8 20 TComboBox / TMyComboBox
9 31 TComboBox / TMyComboBox
10 12 TEdit / TAltEdit
Раскрывающиеся списки (поз. 7 и 8) содержат значения ключей соответственно из разделов [RenameSearchFind] и [RenameSearchReplace] файла конфигурации.

В заключение традиционно приведу информацию для программистов. Эксперименты показали, что управлять окном Multi-Rename Tool проще всего, меняя текст дочерних окон и получая к ним доступ по индексу. Доступ по классу менее эффективен, поскольку в окне много однотипных дочерних окон. Не только индексация, но и классы окон меняются от версии к версии. В таблице приводятся описания только тех окон, на которые можно воздействовать напрямую, с помощью изменения текста в окне.


Навигация в Total Commander

Одно из значений слова "commander" - "капитан корабля". Показательно, что иконка Norton Commander, предшественника Total Commander, изображала фуражку морского офицера - черный с золотом низ, белый верх... А разве может капитан корабля быть слабым в навигации? Это - одна из основных функций любого файлового менеджера, и Total Commander не может быть исключением.

Под навигацией понимается совокупность средств, позволяющих быстро, просто и наглядно осуществлять переход в любое место, причем не только в директорию на диске, но и в папки сетевого окружения, и даже на ftp-сайт.


Способ первый. Меню часто посещаемых директорий

По-английски это звучит как Directory hotlist - "Горячий список директорий". По-русски его иногда называют "меню часто используемых каталогов", но с тем же успехом его можно назвать и "меню часто посещаемых директорий". Это меню - наиболее мощное и удобное средство навигации.

Как его вызвать? Существует по меньшей мере 4 приема - выбирай любой.

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

Если вы там этой кнопки не видите, значит, следует сперва включить ее в конфигурации: "Layout \ Show buttons for history list and hotlist" или просто выдать команду cm_VisHistHotButtons.

Во-вторых, можно нажать на клавиатуре Ctrl+D (от слова "Directory").

В-третьих, можно дважды щелкнуть мышью на строке пути (о ней речь ниже). Этот прием был основным "мышиным" до выхода версии 6.0, когда и появилась кнопка со звездочкой.

Можно, наконец, создать на панели кнопку с внутренней командой cm_DirectoryHotlist, и нажимать ее мышью.

Лично я предпочитаю первый способ. Его преимущество перед вторым состоит в том, что по Ctrl+D меню вызывается всегда на текущей панели, а с помощью мыши можно вызвать его на любой, поскольку кнопок две.

Если вы не занимались настройкой этого меню, самое время начать.

Итак, попробуем вызвать меню любым из описанных способов и увидим вот что:

Давайте сначала нажмем "Add current dir" - "Добавить текущую директорию". Возникнет диалоговое окно, где можно, во-первых, ввести название пункта меню. По умолчанию предлагается имя текущей директории (без пути). Но можно ввести любое подходящее имя, в том числе и русскими буквами, и с пробелами:

Во-вторых, птица "Also save the target dir" приводит к сохранению не только текущей директории (источника), но и противоположной (приемника). Тогда, вызвав данный пункт из меню, мы поменяем путь в обеих панелях. Зачем это может пригодиться?

Допустим, я часто закачиваю фотографии кота на сайт по протоколу ftp. Тогда, заходя в директорию с портретами, я буду автоматически открывать в противолежащей панели директорию сайта. Или, выбирая среди картинок наиболее удачные, я редактирую их и, доведя до совершенства, копирую в директорию "Лучшие фотопортреты". Прописав эту директорию в качестве целевой, я экономлю время на ее открытии. Иными словами, добавляя директорию в список, следует каждый раз задаваться вопросом: "Нет ли у этого пути спутника, партнера, второго члена пары источник-приемник?". Положительный ответ находится довольно часто. Помимо копирования, имеет смысл подумать о синхронизации.

Закроем окно кнопкой ОК. На первый взгляд, ничего не изменилось. Но, вызвав меню вторично, мы убеждаемся, что изменилось многое:

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

Во-вторых, около имени стоит птица. Она играет ту же роль, что и красный кружочек на планах зданий и парков: "Вы находитесь здесь". Перейдите, например, в родительскую директорию, вызовите меню - птица исчезнет.

В-третьих, слова "Add current dir" изменились на "Remove current dir". И действительно - зачем иметь в меню больше одной ссылки на одну и ту же директорию? Впрочем, если такая необходимость все же возникнет, мы сможем решить и эту задачу - способом, к которому мы скоро обратимся. Правда, птицей будет отмечена всего одна из них - первая.

В-четвертых, возник сепаратор - горизонтальная черта, отделяющая собственно меню от двух команд управления им. Вторая из этих команд "Configure..." - единственное, что осталось (и останется) неизменным. Вот о ней-то мы сейчас и поговорим.

Если вы создаете меню впервые, то, поверьте опыту, самым удобным будет пройтись по всем директориям, которые вы посещаете наиболее часто, и, выполняя уже известную нам команду, "накидать" эти директории в меню в произвольном порядке. Закончив этот увлекательный процесс, выполним команду "Configure..." и попадем в следующее окно:

На скриншоте представлена часть моего собственного меню. Кнопки и поля говорят сами за себя, и все же некоторые пояснения дать необходимо.

"Add Item" - вставка новой команды ниже текущей позиции курсора. Впрочем, ниже или выше - не слишком важно, потому что меню поддерживает перетаскивание мышкой.

"Add Submenu..." - не будь этой команды, от меню было бы мало проку - два десятка пунктов, и список пришлось бы пролистывать, что не слишком удобно. Но главное - нельзя было бы структурировать меню, организовывать его иерархически. А имея средства создавать меню второго и более низких уровней, мы можем очень быстро найти нужный пункт, даже забыв, где именно он находится.

Разумеется, название самого подменю не может быть командой, и поля "Command" и "Target path" окажутся недоступными для ввода. Обратим внимание, что перед этим названием ставится знак "минус" - он помогает визуально отличить его от команды. Кроме того, уровни меню показываются сдвигом вправо и двумя минусами в конце.

"Delete Item" - удаление текущего пункта. Если он - название подменю, то все его подпункты перемещаются на уровень вверх.

"Change Title..." - изменение имени пункта.

"Target path" - путь, открывающийся на противоположной панели при выполнении команды. Поле может быть пустым.

"Command" - самое функциональное из полей. Что же оно может содержать?

Прежде всего - то, ради чего меню часто посещаемых директорий и создавалось - "досовская" команда cd (change directory) и путь. Именно так будут выглядеть команды, добавленные из самого Total Commander с помощью "Add current dir". Однако если вы думаете, что этим возможности поля "Command" ограничиваются, то вы были несчастливы в своем заблуждении.

Начиная с версии 5.51, поле "Command" может содержать любую внутреннюю или любую пользовательскую (em_...) команду Тotal Сommander - стоит лишь щелкнуть мышью на кнопке с лупой.

Но и это еще не все. В поле "Command" можно ввести имя файла, и выполнение этой команды будет эквивалентно двойному щелчку на нем! Захотели запустить Word, пишем в поле "d:\Utils\Office2000\Office\WINWORD.EXE", хотим, кроме того, загрузить в него файл, указываем только имя doc-файла, и т. д.

Однако и команда cd - это намного больше, чем ее DOS-предшественница. Например, у меня установлен FS-плагин TurboRegistry. Единожды найдя в нем ветки, в которые мне приходится часто заходить, я добавил их в меню, и теперь буквально двумя щелчками мыши я могу забраться в самые глухие дебри системного реестра. Представляете, сколько щелчков мне бы потребовалось в Registry Editor'е?!

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

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

Напоследок сделаю еще несколько замечаний.

Из данного файла, кстати, следует, что "пунктом меню" считаются не только команды как таковые, но также сепараторы, и те самые минусы, определяющие уровни подменю. Следует учитывать, что максимальное количество пунктов равно 200. Много это или мало? На момент написания этих строк у меня их 149, и это число за последнее время менялось незначительно. Причем командам навигации как таковым соответствуют всего 107 из них. Кому-то, возможно, двухсот пунктов не хватит, и тогда на помощь приходят другие способы навигации, к которым мы сейчас и перейдем.


Способ второй. Кнопки на панели

"Возьмите" мышью папку, куда вам хочется быстро попадать, и просто перетащите ее на панель кнопок. Затем щелкните на появившемся значке правой кнопкой мыши и выберите "Change...". Что мы видим? Все та же команда cd вновь подставлена автоматически, и остается лишь придумать подходящее имя и выбрать соответствующую иконку.

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

Второй способ можно посоветовать для тех директорий, куда в течение короткого времени (скажем, в период выполнения какой-нибудь работы) приходится попадать/копировать особенно часто. После завершения работы кнопку можно удалить.


Способ третий. История посещенных директорий

Кнопка, вызывающая список тех директорий, где мы побывали, расположена справа от звездочки, и имеет вид стрелки вниз:

Без помощи мышки историю активной панели можно вызвать клавишами Alt+Down. Обратим внимание, что у каждой панели - своя история, а вот меню часто посещаемых директорий - одно на всех.

Нажимать эту кнопку имеет смысл не сразу после запуска Total Commander, а погодя, попутешествовав по достаточно большому числу путей. Текущий (отмеченный уже знакомой птицей) по умолчанию будет последним, а в верху списка будет располагаться путь, посещенный первым. Интересно, что и этот порядок можно изменить - в конфигурации за него отвечает ключ ReverseHistory. Чего же там только нет!

По истории посещенных директорий можно гулять назад и вперед, даже не вызывая списка. Во-первых, клавишами Left и Right при нажатом Alt. Во-вторых, колесом мыши при нажатом Shift.


Способ четвертый. Кнопки из меню Layout

Название, может, и не совсем красивое, зато понятное:

Управлять тем, показываются эти кнопки или нет, можно из конфигурации "Layout". Для этой же цели предназначены команды cm_VisDriveButtons и cm_VisTwoDriveButtons, то есть для того, чтобы скрыть/показать эти кнопки, не обязательно заходить в диалог конфигурации.

Информация о кнопках сведена в таблицу:
Кнопка
Клавиши
Команда
Диск абсолютно cm_GotoDriveA ... cm_GotoDriveZ,
относительно cm_GotoPreviousDrive, cm_GotoNextDrive
Корень Ctrl+\ cm_GoToRoot
Родительская директория BackSpace cm_GoToParent

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


Способ пятый. Дерево директорий

Что такое directory structure order - "порядок структуры директорий"? Удобнее всего понять смысл этого термина в тех файл-менеджерах, которые наглядно показывают иерархическую (древовидную) структуру директорий. Так вот, если "раскрыть" все ветви, то directory structure order будет определяться позицией директории в списке: чем выше она в списке, тем выше согласно порядку структуры директорий. Формально говоря, этот порядок совпадает с алфавитным порядком полных путей.

Ярчайший представитель таких программ - Проводник. Однако и Total Commander не только умеет это не хуже, но и обладает множеством дополнительных функций, связанных с деревом директорий на диске.

Минусы в белых квадратиках указывают на то, что все поддиректории "раскрыты", а если какая-то ветвь "свернута", минус изменится на плюс.

В первом случае навигация становится как никогда наглядной: весь диск перед глазами! Стоит найти нужную директорию в списке, щелкнуть на ней, и она будет открыта в противоположной панели. Если там мы переключимся на другой диск, то и "дерево" поменяется, показав структуру этого диска.

К сожалению, у Tree view есть и недостатки. В частности, он не всегда оперативно реагирует на изменение структуры, то есть на удаление и создание директорий. Чтобы привести вид в соответствие с реальностью, необходимо выдать команду cm_RereadSource (F2 или Ctrl+R). Обновление информации может занимать достаточно заметное время, особенно для больших дисков со сложной многоуровневой структурой.

Перемещаться по дереву с помощью клавиатуры можно двумя способами: нажимая Up/Down или Left/Right. В первом случае курсор будет "ходить" только по тем директориям, которые показаны в дереве, вне зависимости от того, свернута или раскрыта эта ветвь. А вот нажимая "влево/вправо", мы перемещаемся по директориям строго в том порядке, в каком они входят в структуру. Если какая-то ветка свернута, она раскроется.

Опишем два ключа конфигурации, имеющие непосредственное отношение к Tree view:

Autotreechange. Если ключ равен 0, то для перехода в текущую директорию понадобится дополнительный щелчок мышью или нажатие Enter. Я предпочитаю значение 1: тогда директория показывается сразу.

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

Есть еще одна команда, связанная со структурой директорий: cm_CDtree (Alt+F10):

Как видно, окошко допускает "быстрый поиск" нужной директории, подобный быстрому поиску файла в обычной файловой панели. При этом "отношения с родителями" не играют роли - только имя.

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


Способ шестой. Переход в следующую/предыдущую директорию

Дабы избежать проблем, присущих Tree view, но сохранить возможность перемещаться по директориям согласно их порядку в структуре, я воспользовался идеей Gregory и написал 6 скриптов на все случаи жизни. С тех пор не проходит дня, чтобы я не вызвал свои скрипты - это чрезвычайно удобно. Остается лишь недоумевать, почему столь важные и очевидные способы навигации не входят в число команд Total Commander.


Способ седьмой. Строка пути (path field)

Эта строка расположена между вкладками и названиями колонок файловой панели:

Отключать ее командой cm_VisCurDir или через конфигурацию категорически не рекомендуется. Мало того, что она напоминает вам текущий путь, но еще и дает доступ сразу к двум средствам навигации.

Начиная с версии 6.50, можно мгновенно попасть в родительскую директорию любого уровня. Для этого надо навести курсор на строку пути, нажать Shift и щелкнуть по любой директории. Например, находясь в D:\Graphics\Viewers\Acrobat\Reader\plug_ins\PictureTasks\OLS\Locale\ENU, щелкнем при нажатом Shift по слову "Graphics" - и молниеносно там же (D:\Graphics) и окажемся.

Более того - можно войти в эту строку и отредактировать путь напрямую. Пожалуй, наибольший смысл это имеет, если путь содержится в буфере обмена. Правда, еще проще в таком случае выполнить скрипт GoClippedPath.

Попасть в строку пути можно несколькими способами. Самый простой - навести курсор на строку справа от пути и нажать левую кнопку. Там же работает и автозаполнение (auto-complete), если, конечно, установлен соответствующий ключ конфигурации.

Напоминаю, что двойной щелчок на той же строке вызывает меню часто посещаемых директорий.

Второй, самый примитивный способ - выполнить команду cm_EditPath (через кнопку или горячую клавишу), а самый изящный - последовательностью Home и Shift+F6. Изящество лично я вижу в следующем. Нажав Home, мы перемещаем курсор на "вход в директорию", на строку "..". А затем мы даем команду на переименование, точнее, "переименование на месте" (inplace renaming). Поскольку текущая строка "возглавляет" директорию, Total Commander воспринимает команду как попытку "переименовать", то есть сменить текущий путь, и устанавливает курсор в заголовок панели.


Способ восьмой. Дерево директорий в отдельном окне

Данная возможность появилась в версии 7.0. Вряд ли имеет смысл подробно рассказывать об этом способе - все слишком очевидно. Создайте кнопки (или назначьте горячие клавиши, или сделайте и то и другое) для следующих внутренних команд:

cm_SeparateTreeOff=3200;Disable separate tree panel
cm_SeparateTree1=3201;One separate tree panel
cm_SeparateTree2=3202;Two separate tree panels
cm_SwitchSeparateTree=3203;Switch through tree panel options
cm_ToggleSeparateTree1=3204;One separate tree panel on/off
cm_ToggleSeparateTree2=3205;Two separate tree panels on/off

и понажимайте их всласть. Следует отметить, что "дерево в отдельном окне", в отличие от дерева Tree View (см. Способ пятый), реагирует на изменение структуры (создание и удаление директорий) мгновенно. Если вы предпочитаете отдельную панель для этих команд, то вот сделанная мной библиотека иконок, а вот и сама панель.


Способ девятый. Команда CD путь

Это - тоже долгожданное нововведение "семерки". Среди внутренних команд появились команды с параметрами. К навигации непосредственное отношение имеют две из них: CD путь и FTPOPEN имя_ftp_соединения. Разумеется, любой из этих команд с тем или иным параметром можно присвоить и кнопку на панели, и горячую клавишу.


Способ десятый. Breadcrumb bar

...Поймал себя на мысли, что с выходом каждой новой версии Total Commander я выполняю однотипную работу: открываю статью, которую вы сейчас читаете, и вписываю главу "Способ -дцатый" о навигации. Не успели еще "высохнуть чернила" на двух предыдущих главах, как вышла версия 7.5, подарившая миру новый способ путешествий по директориям (как будто и без того мало) под загадочным названием Breadcrumb bar (в русском переводе "Цепочки навигации").

Включать и выключать эти самые цепочки можно командой cm_VisBreadCrumbs. При включении слева от строки текущей директории появляется стрелочка вниз, похожая на ту, что описана в Способе третьем. При наведении курсора на эту стрелочку вываливается графическое меню, открывающее доступ ко всем элементам файловой системы (диски, рабочий стол, "Мои документы" и прочему), куда можно попасть с помощью Total Commander. Собственно, проще взглянуть на скриншот:

Если продвинуть курсор к пункту со стрелочкой вправо, путешествие продолжится! А вот закончится оно щелчком мыши на нужной директории и попаданием в нее.

Начинать путешествие можно и с любой директории, родительской относительно текущей: нужно лишь навести курсор на ее имя, и через некоторое время (о длительности его мы поговорим несколько позже) из нее "вывалится" еще одно меню. Как и ранее, щелчок мышью осуществляет переход к выбранной директории. Похожий способ навигации (см. Способ седьмой) работал и в предыдущих версиях. Изменилось то, что при нажатой клавише Shift директория открывается в новой вкладке, при простом щелчке - в текущей.

Перечислим те ключи раздела [Configuration] файла wincmd.ini, которые имеют отношение к breadcrumb bar.

BreadcrumbSeparator задает начало области, куда необходимо указать курсором мыши для открытия подменю директорий. Положительные числа 0..100 соответствуют проценту от длины строки. Значение 0 указывает, что используется все меню (я так и установил). Если же число отрицательное, то единица измерения оказывается другой, а именно - высота строки. Отсчет идет справа.

BreadCrumbMaxWidth задает ширину breadcrumb bar в пикселях (не меньше 100).

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

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

BreadcrumbDelayDir: То же, на открытой поддиректории.

BreadcrumbDelayFtp: То же, для FTP-соединения.

BreadcrumbdelayPlugin: То же, для FS-плагинов.

BreadcrumbDelayVirtual: То же, для виртуальных папок типа Рабочего стола.

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

"Клавишникам" (тем, которые любят все команды выполнять, не трогая мышь) на заметку: вызвать панель breadcrumb bar можно клавиатурной комбинацией Alt+F11 (левая панель) или Alt+F12 (правая). Попав в строку текщего пути, можно путешествовать по ней курсорными клавишами и табуляцией. Нажав Down, открываем меню поддиректорий, нажатие Enter осуществляет переход.


Способ одиннадцатый. Локальный url-файл

Если "взять" левой кнопкой мыши строку адреса в браузере и перетащить в панель Total Commander, там образуется файл с именем, совпадающим с именем текущей страницы, и с расширением url (Uniform Resource Locator). Двойной щелчок по такому файлу приведет к строго обратному событию: открытию данной страницы в браузере.

Все это давно известно. Но автору Total Commander пришло в голову использовать тот же формат для несколько иной цели – хранить в таких файлах ссылки не на глобальный ресурс, а на локальный, то есть директорию. Начиная с версии 9.0, в подобный файл, а точнее, в значение ключа URL раздела [InternetShortcut], можно занести имя локальной директории. Тогда двойной щелчок на таком файле откроет данный путь в текущей панели. Чтобы использовать эту возможность, надо задать значение ключа OpenUrls в конфигурации равным 1, чтобы отключить - 0.

Для упрощения создания url-файлов написан скрипт, который создает в активной панели url-файл с заданным именем и помещает в него путь из буфера обмена. Если же информация в буфере не соответствует никакому пути на данном компьютере, используется путь из пассивной панели.


Другие способы навигации

А вы думали, это все? Как бы не так!

Следующий совет придется по душе "клавишникам". Можно ли перейти в произвольную директорию нажатием клавиатурной комбинации? Обращаю их внимание на то, что все ранее обсужденные способы навигации либо имели горячие клавиши по умолчанию, либо допускали их назначение. То же касается и команды перехода в произвольную директорию. Войдите в меню Start и создайте новую команду "cd путь". Уже там можно выбрать горячую клавишу вида Ctrl+Alt+Fn или Ctrl+Alt+Shift+Fn, где n - число от 1 до 12, и на этом успокоиться. Правда, такие комбинации не отличаются мнемоничностью - как запомнить, что переход в директорию с файлами Word производится клавишами Ctrl+Alt+Shift+F4? Возможно, нам захочется назначить что-нибудь типа Ctrl+W. Ну что же, это потребует чуть больше времени. Осталось отредактировать файл команд Totalcmd.inc, после чего добавленной нами команде можно будет сопоставить горячую клавишу ничуть не хуже, чем любой внутренней.

Да и кроме того, к услугам клавишников - командная строка, понимающая инструкцию cd без переводчика.

Далее, Total Commander поддерживает псевдопеременные окружения, которые можно использовать в команде cd. Полный список этих переменных и рекомендации по их использованию можно найти в справке. Здесь они не приведены, поскольку их список постоянно пополняется.

Эти переменные, при всех своих преимуществах, имеют и недостатки. Например, создав в меню часто посещаемых директорий команду cd псевдопеременная, выполнив эту команду и вновь открыв меню, мы не увидим птицу напротив пункта.

Ну, и напоследок приведу отрывок из Totalcmd.inc - команды, осуществляющие переход в различные виртуальные папки:

cm_OpenDesktop=2121;Desktop folder
cm_OpenDrives=2122;My computer
cm_OpenControls=2123;Control panel
cm_OpenFonts=2124;Fonts folder
cm_OpenNetwork=2125;Network neighborhood
cm_OpenPrinters=2126;Printers folder
cm_OpenRecycled=2127;Recycle bin

Я наверняка что-то упустил. Скорее всего, существуют еще какие-то средства навигации, ускользнувшие от моего внимания. И нет ничего удивительного - даже более чем десятилетний стаж работы с Total Commander оставляет место для постоянных открытий и находок.


Передача пути из Total Commander в PowerPro

У опытных пользователей (а именно им предназначена данная статья) название наверняка вызовет удивление: "А что тут думать? %P, и дело с концом!". Но я утверждаю, что не все здесь так очевидно. Если уточнять постановку задачи, то требуется передать в скрипт PowerPro полный путь (имя директории и файла) из Total Commander в самом общем случае.

Итак, для начала выйдем в корень диска c. Задача проста - передать имя этой директории в скрипт PowerPro. Его код предельно краток:

args Path
win.debug("Path: '", Path, "'")

Далее, создаем кнопку с вызовом скрипта runfile.test(%P), где test.powerpro или test.txt - имя скрипта. Мы желаем увидеть в окне отладки буквально следующее:

Path: 'c:\'

Но нашим желаниям сбыться не суждено. Ошибка возникает уже на первом операторе, где PowerPro пытается присвоить переданный параметр локальной переменной Path:

Bad expression: invalid operator at
:\)
runfile.test(c:\)

Последняя строчка нас, казалось бы, полностью удовлетворяет, но почему "откусывается" первый символ аргумента?

Дело, видимо, в том, что оператор args Path, как гласит руководство по PowerPro, в точности эквивалентен оператору local Path = arg(1), который по сути своей есть оператор присваивания. После знака = интерпретатор видит символ c, то есть не ждет ни числа, ни символьной константы, которая заключается в кавычки. Итак, будучи готовым к восприятию переменной или функции, интерпретатор встречает далее символ :, который не может входить ни в то, ни в другое!

Уже упомянутое руководство буквально пестрит фразами типа "Plain text does not usually need to be in quotes (except for filenames containing spaces)". Вроде бы, путь c:\ пробелов не содержит, и все должно пройти гладко, но...

Что же, давайте исправим вызов: runfile.test("%P") и преуспеем, получив ожидаемое сообщение в окне отладки.

Усложняем задачу: создаем директорию с полным путем c:\Utils\Test\Dir Name with Spaces, то есть посмотрим, как Total Commander в PowerPro на пару справляются с путем, содержащим пробелы. Входим в эту директорию (неважно, есть ли в ней файлы и куда установить курсор, ведь параметр %N нас пока не интересует). Запуск скрипта приводит к желаемому

Path: ' c:\Test\Dir Name with Spaces\ '

Пусть нас не смущают пробелы вокруг пути - это "косметика", привнесенная PowerPro. Впрочем, не грех и убедиться:

win.debug(length(Path), length("c:\Test\Dir Name with Spaces\"))

Мы увидим строку

 29 29

что как прямо (длины равны), так и косвенно (пробелы вставлены автоматически) подтверждает нашу догадку.

Опять усложняем задачу - создадим файл с полным путем c:\Test\Dir Name with Spaces\File Name with Spaces.txt и усовершенствуем скрипт:

args Path, Name
win.debug("Path: '", Path, "', Name: '", Name, "'")

Вызов тоже придется подправить: runfile.test("%P", %N)

Результат:

Path: ' c:\Test\Dir Name with Spaces\ ', Name: ' File Name with Spaces.txt '

Казалось бы - все замечательно, но радоваться, увы, рано.

Создаем файл с полным путем c:\Test\Dir Name with Spaces\FileNameWithoutSpaces.txt, иными словами, в той же директории (имя с пробелами) создаем файл, имя которого пробелов не содержит.

Исполнение скрипта приводит к сообщению об ошибке:

Invalid use of period: cannot load plugin, invalid handle value, or invalid function. FileNameWithoutSpaces

После нажатия ОК отладочное окно все же появляется:

Path: ' C:\Test\Dir Name with Spaces\ ', Name: ' '

Иными словами - не встретив никаких трудностей в обработке пути (с пробелом), PowerPro не сумела обработать обычное имя FileNameWithoutSpaces! Нетрудно догадаться, что, присваивая это значение (без кавычек) переменной Name, интерпретатор PowerPro пытался истолковать его как имя переменной или функции и, разумеется, потерпел неудачу.

Вновь упростив скрипт до

args Name
win.debug("Name: '", Name, "'")

и изменив вызов на runfile.test(%N), мы убеждаемся, что аргумент Path никак на результат не влияет.

Но теперь мы уже знаем, что делать: runfile.test("%P", "%N").

И ситуация меняется на противоположную! Курсор на файле FileNameWithoutSpaces.txt, результат:

Path: ' C:\Test\Dir Name with Spaces\ ', Name: ' FileNameWithoutSpaces.txt '

что вдохновляет, однако

Bad expression: invalid operator at
File Name with Spaces.txt"")
runfile.test(""File Name with Spaces.txt"")

если текущим файлом является File Name with Spaces.txt... Ну что ты будешь делать!

Внимательное изучение сообщения об ошибке позволяет разглядеть "удвоенные двойные" кавычки вокруг имени файла. Вот что получилось: Total Commander, "увидев" в качестве аргумента-файла имя с пробелами, автоматически добавляет кавычки вокруг имени. Собственно, об этом сказано и в руководстве к Total Commander: "Names containing spaces will be surrounded by double quotes. Do NOT put quotes around %P%S yourself!"

Вот какие мы бестолковые - нарушили требование автора программы и еще удивляемся!

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

Допускается предварять закавыченный параметр знаком вопроса (вот так: ?"%P"). Эту рекомендацию можно, во-первых, найти в руководстве по PowerPro (хотя в весьма неявной форме). Во-вторых, мне об этом написал пользователь из Германии - он не смог запустить один из моих скриптов, пока не догадался приписать вопросительный знак перед параметром. Увы, данный способ тоже работает не всегда. В частности, он не поможет нам в приведенном выше примере.

Между прочим, скрипт все-таки можно заставить работать, заменив кавычки на другой символ: runfile.test(?|%P|, ?|%N|). Вместо | подойдет и "плюс", и вообще любой не буквенный и не цифровой символ.

В любом случае результаты будут таковы:

Path: ' C:\Test\Dir Name with Spaces\ ', Name: ' "File Name with Spaces.txt" '
Path: ' C:\Test\Dir Name with Spaces\ ', Name: ' FileNameWithoutSpaces.txt '

Эти результаты помогают наконец-то обнаружить источник неприятностей.

Несмотря на то, что скрипт перестал выдавать ошибку, полученные результаты нельзя признать правильными. Почему? Простой вопрос: как получить полное имя текущего файла? Казалось бы, FullPath = Path ++ Name. Это справедливо для второго из наших файлов и совершенно не справедливо для первого: ведь файла с путем C:\Test\Dir Name with Spaces\"File Name with Spaces.txt" не существует, в чем легко убедиться с помощью функции file.validpath.

Это отмечал в своей статье Gregory: "TC очень умно ставит кавычки вокруг имен файлов - только если кавычки нужны. Эта умность здесь очень мешает".

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

Каковы же возможные решения возникшей проблемы?

Решение первое: использование "коротких" имен.

Изменив вызов на runfile.test("%p", "%n"), получаем:

Path: ' C:\Test\DIRNAM~2\ ', Name: ' FILENA~1.TXT '
Path: ' C:\Test\DIRNAM~2\ ', Name: ' FILENA~2.TXT '

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

С одной стороны - теперь скрипт будет правильно работать вне зависимости от наличия пробелов в именах файлов и директорий. Зачастую этого оказывается вполне достаточным - раз программа смогла "свернуть" имя до стандарта 8.3, то сможет и "развернуть", то есть однозначно сопоставить корявому и немнемоничному FILENA~1.TXT наш файл File Name with Spaces.txt.

С другой стороны, данное решение совершенно не годится, например, при операциях с комментариями к файлам (descript.ion), о чем я уже писал в пояснениях к скрипту CopyComment.

Вам нравится это решение? Мне тоже нет.

Решение второе - ручная обработка. Можно было бы назвать его "решение Gregory", но я привнес в это решение свою лепту. "Решение Gregory" в чистом виде дано в его статье, а я предложу свой способ.

Итак, мы используем то, что если после имени скрипта PowerPro стоит знак =, то все, что находится в поле "Parameters", записывается в глобальную переменную x9. То есть мы вынуждены передавать параметры из Total Commander не по одному, а вместе, чохом. Запись %P%N нам вполне подходит. Иными словами, переменной x9 присваивается полный путь текущего файла.

Итак, если мы хотим вызывать скрипт кнопкой на панели Total Commander, нужно:

Код скрипта меняется кардинально:
win.debug("'", x9, "'", length(x9), length("C:\Test\DirNameWithoutSpaces\FileNameWithoutSpaces.txt"))

Как видно, мы начинаем с самого простого случая, когда ни имя файла, ни путь пробелов не содержат. Вторую длину вычисляем в качестве "эталона". Это - истинная длина полного пути, что, кстати говоря, подтверждается полем FullPathLen контентного плагина (Total Commander) filex.

Результат:

'  C:\Test\DirNameWithoutSpaces\FileNameWithoutSpaces.txt ' 55 54

По одному пробелу перед и после имени добавлено по уже известной нам причине, а вот происхождение второго пробела перед именем неизвестно. Длина переменной x9 оказалась, разумеется, на единицу больше "эталона".

Далее, исполнение скрипта

win.debug("'", x9, "'", length(x9), length("C:\Test\DirNameWithoutSpaces\File Name with Spaces.txt"))

дает:

'  "C:\Test\DirNameWithoutSpaces\File Name with Spaces.txt" ' 57 54

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

Чтобы получить "истинный" полный путь, надо:

Вот код скрипта, удовлетворяющего всем случаям:

local FullPath = x9
static Quote = ?+"+
local Path = file.folder(FullPath)
Path = trim(Path, " ", 3)
Path = trim(Path, Quote, 3)
local Name = file.nametype(FullPath)
Name = trim(Name, Quote, 3)
win.debug("Path: '", Path, "', Name: '", Name, "'")

Из результата нетрудно видеть, что полный путь будет образовываться оператором

FullPath = Path ++ "\" ++ Name

потому что функция file.folder отбрасывает завершающий символ "\", в отличие от параметра %P.

Решение третье. Его можно условно назвать "решение через список", потому что искомый полный путь берется из файла-списка. Кто не знает, при указании в поле "Parameters" кнопки Total Commander параметра, например, %L или %F, происходит множество событий, скрытых от глаз пользователя. Во-первых, во временной директории создается файл-список. Имя ему выбирает сам Total Commander, поэтому, разумеется, беспрепятственно получает к нему доступ, даже если полный путь содержит пробелы (а как правило, так оно и есть). Во-вторых, в файл-список заносятся полные пути всех выделенных файлов, или полный путь только текущего, если ничего не выделено. При этом, что немаловажно, никаких кавычек Total Commander не проставляет, записывая в файл имена "как есть". Наконец, в-третьих, по завершении отработки команды, указанной в поле "Command" кнопки, файл-список автоматически удаляется.

Отсюда следует алгоритм получения полного имени файла и код скрипта:

args List
static CR = esc(?+\r+, ?+\+)
static NL = esc(?+\n+, ?+\+)
local FullPath = file.readall(List)
local Path = file.folder(FullPath)
local Name = file.nametype(FullPath)
Name = trim(Name, NL, 2)
Name = trim(Name, CR, 2)
win.debug("Path: '", Path, "', Name: '", Name, "', ", Panel)

Как известно, при закрытии файла в него дописываются спецсимволы: сначала "новая строка", а потом "возврат каретки". Удалять их приходится в обратной последовательности. Вызов скрипта имеет вид runfile.test("%L").

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

Напоследок рассмотрим "высший пилотаж" передачи параметров, а именно - вытаскивание из Total Commander полного пути текущего файла вообще без опоры на параметры кнопки %P и %N. Зачем, спросите вы? Ну, как минимум чтобы избежать излишней "умности". Но есть еще по меньшей мере два случая, когда отказ от параметров Total Commander может пригодиться.

Случай первый - панель PowerPro.

Параметры %P, %N и подобные им - "внутреннее дело" Total Commander, его кнопок и горячих клавиш. Многочисленные панели PowerPro (типа bar, menu, showfile и др.) ничего не знают об этих параметрах и знать не хотят.

Случай второй - движение мыши.

В PowerPro можно приписать выполнение скрипта множеству движений мыши - скажем, "удару" (bump) по краю экрана, или движение мышиного колеса вперед-назад, или горизонтальному "росчерку" (stroke). Я уж не говорю о плагине mousegesture, с помощью которого можно писать на экране буквы (типа системы "Граффити" в бесклавиатурных КПК). Так или иначе, такие операции ничуть не больше, чем панели, осведомлены о параметрах Total Commander. Зато они очень хорошо понимают, что такое "дескриптор" и "отправка сообщений окну". Вот этим-то мы и воспользуемся.

Итак, код скрипта:

clip.save
//сохраним буфер обмена - вдруг там что-нибудь ценное?
local hwnd = win.handle("c=TTOTAL_CMD")
//получим дескриптор окна Total Commander
clip.clear
//на всякий случай очистим буфер
win.sendmessage(hwnd, 0x400+51, 2018, 0)
//пошлем окну Total Commander сообщение cm_CopyFullNamesToClip=2018;Copy names with full path
wait.for(clip.get)
//подождем, чтобы буфер был непустым - это значит, что предыдущая команда выполнена
local FullPath = clip.get
//получим содержимое буфера и присвоим локальной переменной FullPath
clip.load
//восстановим сохраненный буфер - наши данные в сохранности
local Name = file.nametype(FullPath)
//находим имя файла
local Path = file.folder(FullPath)
//находим путь
win.debug("Path: '", Path, "', Name: '", Name, "'")
//проверим, все ли в порядке

Казалось бы, все действительно в порядке - имена файлов и директорий передаются корректно, вне зависимости от пробелов в них. Но есть одно "но". Если установить курсор не на имени файла, а на "вход в директорию" (самая верхняя строчка панели Total Commander), скрипт выдаст ошибку: No files selected. Ошибка возникает на строке win.sendmessage(hwnd, 0x400+51, 2018, 0). Это давно известная и от этого не менее неприятная особенность Total Commander. Что же, придется ее обходить.

clip.save
//сохраним буфер обмена - вдруг там что-нибудь ценное?
local hwnd = win.handle("c=TTOTAL_CMD")
//получим дескриптор окна Total Commander
local Panel = ifelse(tc.active(hwnd) == "left", 8, 7)
//получим индекс активной панели Total Commander: Panel = 8 - левая, Panel = 7 - правая
local TMLB = childwin.handle(hwnd, "TMyListBox", Panel)
//получим дескриптор активной панели Total Commander (класс TMyListBox)
local Result = win.sendmessage(TMLB, 0x0188, 0, 0)
/*отправив это сообщение окну класса TMyListBox, мы узнаем индекс текущего элемента списка (list item).
Входу в директорию соответствует индекс 0, первому файлу (или поддиректории) - индекс 1, и т. д.*/
clip.clear
//на всякий случай очистим буфер
win.sendmessage(hwnd, 0x400+51, 2029, 0)
/*пошлем окну Total Commander сообщение cm_CopySrcPathToClip=2029;Copy source path to clipboard,
то есть буфер обмена содержит только текущий путь.
Разумеется, даже при отсутствии текущего файла ошибки не возникнет*/
wait.for(clip.get)
//подождем, чтобы буфер был непустым - это значит, что предыдущая команда выполнена
local Path = clip.get
/*получим содержимое буфера и присвоим локальной переменной Path. Путь известен, половина задачи выполнена*/
local Name
/*объявим локальную переменную Name, в которую будет записано имя текущего файла (или директории).
Пока значение переменной Name - пустая строка*/

if(Result) do
	//если Result отличен от нуля, значит, курсор стоит не на входе в директорию
	win.sendmessage(hwnd, 0x400+51, 2017, 0)
	/*пошлем окну Total Commander сообщение cm_CopyNamesToClip=2017;Copy filenames to clipboard,
	то есть буфер обмена содержит только имя текущего файла*/
	wait.for(clip.get)
	//подождем, чтобы буфер был непустым - это значит, что предыдущая команда выполнена
	Name = clip.get
	/*получим содержимое буфера и присвоим локальной переменной Name. Имя известно, задача выполнена*/
endif

clip.load
//восстановим сохраненный буфер - наши данные в сохранности
Panel = ifelse(file.isfolder(Path ++ "\" ++ Name), "directory", "file")
/*переменной Panel (в прежней роли она нам больше не нужна) присвоим значение "directory",
если путь Path ++ "\" ++ Name - это путь к директории, а не к файлу, и значение "file" - в противном случае*/
win.debug("Path: '", Path, "', Name: '", Name, "', ", Panel)
//проверим, все ли в порядке

Напомним, что если переменная Name имеет значение "пустая строка", то курсор установлен на входе в текущую директорию. К тому же выводу приводит истинность условия Result == 0.

Разумеется, способ передачи параметров через буфер будет работать и с кнопки Total Commander, и с горячей клавиши. Возможно, его следует рассматривать как самый универсальный и надежный способ. Можно пойти и дальше - написать вспомогательный скрипт и вызывать его из других, нуждающихся в пути/имени текущего файла.

Попробую подвести итог.

Обширная практика показывает, что большинство ваших скриптов будут работать правильно, если использовать заглавные буквы в обозначениях параметров ("длинные пути") и кавычки ("%P"). Предоставив обеим программам самим разбираться с лишними пробелами и кавычками, мы обычно достигаем успеха. Пресловутая "умность", как правило, все же помогает, а не мешает. Но "как правило" и "всегда" - разные вещи!

Хочется надеяться, что мои исследования, описанные выше, окажутся полезными тем, кто использует широчайшие возможности PowerPro для работы в Total Commander. Или наоборот.

…Все вышеизложенное было актуально для Total Commander версии ниже 9.0, в которой, уступая многочисленным просьбам, Кристиан Гислер наконец-то ввел возможность получать дескрипторы многих элементов окна Total Commander, в том числе строк левого, правого, пассивного и активного файловых списков. Сбылась мечта скриптописцев: корректно определяются не только сами пути, но и активность панелей! Я написал подпрограмму, возвращающую путь текущей панели (причем это не единственный способ):


local hwnd = win.handle("c=TTOTAL_CMD")
local Left = win.sendmessage(hwnd, 0x400+50, 1, 0)
local Active = win.sendmessage(hwnd, 0x400+50, 3, 0)
local Hand = win.sendmessage(hwnd, 0x400+50, ifelse(Active == Left, 9, 10), 0)
quit(file.folder(win.gettext(Hand)))

Разумеется, теперь ни кодировка символов в пути, ни наличие в нем пробелов не представляют проблемы. Хотя определение имени текущего файла по-прежнему в общем случае приходится проводить обходными маневрами.


Обзор временных панелей Total Commander

Данная статья ставит своей задачей обзор и сравнение так называемых временных панелей файлового менеджера Total Commander. Я буду использовать обозначение ВП, где букву "В" можно расшифровать и как "временная", и как "виртуальная", а "П" - "панель" или "папка".

В обзоре будут рассмотрены следующие плагины:

Название
Версия
Автор
Иконка
File Redirector 5.4 DandLs (destman,logosman)
FileCatalog 0.1 AlecP
Temporary Panel 1.0 Sergey Puljajev
Temporary Drive 1.5 Igor A. Labutin
Virtual Panel 1.0.0.494 MVV

Я оставил за рамками своей статьи Virtual Disk. Он ориентирован почти исключительно на работу с образами дисков, функцию работы со ссылками на обычные файлы рассматривая как побочную. В частности, внутри ВП невозможно создать директорию, а при копировании физической директории внутрь ВП копируются только ссылки на файлы, кучей накапливаясь в корне ВП. Нельзя также ни скопировать файл изнутри ВП в директорию на диске, ни просмотреть или запустить файл.

Прежде всего - как установить такой плагин? (Это информация для новичков, знатоки могут пропустить данный абзац). Плагин файловой системы, скорее всего, упакован в zip-архив. Результат входа в него может быть разным: если версия Total Commander равна 6.50 и выше, и если автор плагина обеспечил такую возможность, будет произведена так называемая автоустановка. Можно положительно ответить на все вопросы и на этом установку закончить. В противном случае:

  1. Создать директорию с соответствующим именем, скажем, "SomeTempPanel" как поддиректорию Total Commander (обычно это c:\Program Files\Total Commander);
  2. Распаковать туда содержимое архива;
  3. Из меню открыть страницу настройки плагинов (Configuration\Plugins);
  4. Нажать кнопку "Configure" рядом с рамкой "File system plugins (.WFX)";
  5. Нажать "Add";
  6. Найти директорию SomeTempPanel и в ней выбрать файл с расширением WFX.

Теперь при переходе в Сетевое окружение (Network neighborhood) вы увидите директорию с именем нового плагина. Эта виртуальная директория и есть ВП.

Зачем нужна ВП? Я приведу здесь далеко не полный список ее возможных функций.

Задача каталогизации столь важна, что для ее решения под Total Commander уже написано несколько архиваторных плагинов, например, Catalog Maker, DiskDir и его развитие DiskDirExtended. Но, по крайней мере, решающих преимуществ у таких плагинов перед ВП нет. Базы и в том, и в другом случае представляют собой небольшие по объему файлы, которые не захламляют дисковое пространство. Разве что серьезным аргументом можно считать совместимость форматов. База DiskDir - это просто список файлов, которые можно просмотреть и отредактировать в любом текстовом редакторе. Но и некоторые ВП (например, Temporary Panel) также ведут базу ссылок в обычном текстовом формате. Тот же плагин можно настроить на работу с базами этими самых архиваторных каталогизаторов, причем как Catalog Maker, так и DiskDir.

Еще одно возражение против ВП: то же самое, пользуясь услугами файловой системы, можно организовать с помощью жестких ссылок (hard links). Но, во-первых, для этого необходима NTFS, а я точно знаю, что многие до сих пор "сидят" на FAT32. Во-вторых, для понимания "идеологии" жестких ссылок необходимо некоторое мозговое усилие, что в ряде случае вызывает сложности. В-третьих, прямую аналогию между этими методами провести можно далеко не всегда.

Теперь рассмотрим свойства различных ВП. Вначале сделаю несколько вводных замечаний, а заодно определюсь с терминологией.

Какова цель пользователя, установившего курсор на ссылку и нажавшего клавишу Del или F8? Хочет ли он удалить только ссылку или сам файл, на который она указывает? Видимо, ответ может быть разным в зависимости от обстоятельств. Поэтому было бы разумно обеспечить как то, так и другое.

"Обновлением" я называю весьма удобную и в ряде случаев даже незаменимую функцию. Проверяю ее наличие я следующим образом: создаю текстовый файл произвольного содержания и копирую ссылку на него во ВП. Допустим, его объем равен 10 байт. Теперь я стираю один символ из файла и сохраняю его. Если после команды cm_RereadSource (Ctrl+R или F2), выданной из ВП, она показывает объем файла как 9 байт, я делаю вывод о том, что данная ВП обновление поддерживает.

Под "перезаписью" я понимаю бессбойное выполнение операции копирования ссылки из ВП на одноименный файл в директории на диске (например, после редактирования). При попытке выполнить такую операцию из File Redirector появляется странное окно:

Прежде чем переходить к рассмотрению отдельных ВП, отмечу, что все они предоставляют возможности ведения произвольного числа баз и, как следствие, создания нескольких независимых директорий сетевого окружения. В простейшем случае у нас будет зарегистрировано несколько как бы различных плагинов, но использующих один и тот же wfx-файл, скопированный в несколько разных директорий.

File Redirector (FR). Помимо наличия подробной справки, File Redirector привлекает пользователя показом объема директорий, на которые он ссылается. Больше такой функции ни у одной из ВП я не обнаружил: они выполняют ее только по команде cm_CountDirContent.


Окно настройки File Redirector

FileCatalog (FC). Плагин производит странное впечатление. Лаконичность справки резко контрастирует с обилием обещанных в ней функций. Попытки разобраться в возможных комбинациях режимов, групп, команд и результатов нажатий кнопок в окне настройки привели меня к дилемме: либо я недостаточно прозорлив, либо плагин нуждается в серьезной доработке. Слава богу, что хотя бы обеспечиваются базовые функции хранения ссылок на файлы. Виртуальные директории, в отличие от ссылок на директории на диске, отмечаются особым значком, что, безусловно, красиво и удобно. Мало того - ссылки на несуществующие файлы получают иконку, перечеркнутую красным.

Видимо, не в последнюю очередь именно эти красивости заставляют плагин подтормаживать - из всех рассматриваемых ВП вход в FileCatalog занимает наибольшее время.

Кроме того, есть квалифицированное мнение, что File Redirector и FileCatalog не очень корректно работают с памятью.


Окно настройки FileCatalog

Temporary Panel (TP). Настроек много, поддерживается работа с базами Catalog Maker и DiskDir, а также плейлистами (M3U и PLS). Существенное преимущество - текстовый формат базы.


Окно настройки Temporary Panel

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

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

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

На мой взгляд, именно это и называется "медвежьей услугой". Очарованный возможностью выбора, я какое-то время работал с Temporary Panel, но потом отказался от нее. Во-первых, всякий раз при удалении ссылки приходится лишний раз щелкать крысой. Во-вторых, пугает перспектива в один непрекрасный день "промахнуться" и нажать "No" вместо "Yes", удалив тем самым, возможно, очень важный файл. Причем, поскольку сам файл может находиться в глухих дебрях файловой системы и его физическое исчезновение не бросается в глаза, такая потеря может обнаружиться очень поздно, после многократной очистки корзины. В этом смысле я бы предпочел именно более длинный путь, скажем, набор в командной строке "del имя_файла", или физическое удаление только при нажатой клавише Shift, потому что комбинацию Shift+Del в Total Commander я нажимаю редко и только после тщательного обдумывания, когда в самом деле хочу удалить файл мимо корзины.

Temporary Drive (TD). Плагин оставляет очень приятное впечатление. Во-первых, подробное и аккуратное описание функций. Во-вторых, возможность обновления свойств файла - среди рассмотренных ее обеспечивают только Temporary Drive и Virtual Panel. В-третьих, ничего лишнего. В-четвертых, одна полезная функция, вплотную соприкасающаяся с удалением физического файла из ВП.

При установке соответствующего флага в окне настройки (см. скриншот) можно перемещать физический файл, переместив ссылку на него. Правда, команды удаления физического файла все равно нет. То есть если возникнет нужда в таком удалении, приходится выполнять его в два шага - сначала перемещение файла из ВП в произвольную директорию, и лишь затем - удаление его оттуда. Иными словами, плагин все-таки производит физическое удаление файла, но не напрямую. Что удержало автора от добавления такой функции? Видимо, те же самые соображения, которые удерживают меня от постоянного использования Temporary Panel.

Virtual Panel (VP). С того времени, как я опубликовал свою статью, плагин Virtual Panel совершил гигантский скачок, превратившись из "одного из подобных" в "безусловно лучший". Описывать его многочисленные преимущества перед конкурентами - дело бессмысленное, проще установить его и увидеть все своими глазами. Достаточно упомянуть хотя бы собственный скриптовый язык, напоминающий язык batch-файлов. Вот, например, как добавить в панель скрипт, рекурсивно удаляющий из нее ссылки на файлы (но не директории), причем сами файлы, разумеется, не затрагиваются:


<add \>FileDelete { <for %%f . "%1" { <del "%%f" } <for /d! %%d . * { <cd "%%d" <exec \>FileDelete "%1" } }

После этого в панели появляется запись >FileDelete с собственной иконкой и нулевым объемом - это и есть скрипт. Таких скриптов в виртуальной директории и ее поддиректорих можно создать сколько угодно, каждый для своей цели. Используя вышеупомянутый скрипт, удаление можно произвести командой


>FileDelete маска


Окно настройки Virtual Panel

Удобно назначать собственные иконки как для виртуальных папок, так и для ссылок на удаленные файлы и директории. При этом, в отличие от FileCatalog, скорость работы Virtual Panel вопросов не вызывает.

Не обойтись и без недостатков. Virtual Panel не поддерживает собственные пользовательские колонки, поэтому, чтобы узнать путь к файлу, на который указывает данная ссылка, приходится создавать свой набор колонок, например, такой: [=tc.path][=tc.fullname]. Однако переключиться на данный вид, как обычно, через правый щелчок на заголовке панели, получается далеко не всегда, приходится исполнять команду cm_SrcCustomViewХ, где Х - номер набора. Правда, здесь проявляется недостаток самого Total Commander, а не его плагинов.

Еще один упрек в адрес Virtual Panel - скрипты нельзя импортировать в текстовые файлы. Но, во-первых, их можно извлекать из базы (или, как автор ее называет, "файла автозагружаемого состояния"), во-вторых, помогает история командной строки, в которой хранятся последние команды.

Еще одно преимущество Virtual Panel - среди всех ВП он единственный, кто активно развивается. Развернуты дискуссии как на англо-, так и русско-язычных форумах. Новые модификации плагина появляются часто, так что, читая эту статью, вы, скорее всего, будете знакомится всего лишь с его устаревшей версией.

Итоговая таблица свойств временных панелей выглядит следующим образом:

FR FC TP TD VP
Справка txt, chm txt - txt txt
Физическое удаление - - да при перемещении да
Физическое перемещение - - да да да
Обновление - - - да да
Объем директорий да - - - -
Поддержка внутренних ассоциаций - - да - -
Собственные пользовательские колонки - - да - -
Текстовый формат базы - - да - да
Перезапись - - да да да
Ссылки на удаленные файлы хранит хранит, помечает хранит не хранит хранит, помечает
Ведение протокола - - да - да, настраивается
Собственные иконки - да - - да, настраиваются

Подобные обзорные статьи принято завершать выводами и рекомендациями. Дело в том, что функцию хранения ссылок на файлы и директории все описанные плагины выполняют одинаково, и если вам ничего другого не нужно, то можно выбрать любой. Далее идут повышенные потребности. Тем, например, кто сможет разобраться в мощном FileCatalog, придутся по душе его возможности создания групп, копирования свойств и пакетного выполнения команд. Примерно то же можно сказать и о куда более мощных скриптах, исполнение которых поддерживает Virtual Panel. Последний плагин, как видно из таблицы, обладает наибольшим количеством других свойств и функций.

Что же касается меня, то я постепенно осуществляю переход от File Redirector, который ранее был для меня основным, к Virtual Panel. Для простых задач удобно использовать плагин Temporary Drive, подкупающий своим разумным минимализмом.


Xxcopy - могущественный черный карлик

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

Точно так же я не берусь исчерпывающе определить назначение утилиты Xxcopy. Казалось бы, программа расширенного копирования, но это лишь одна из ее функций. Скажем так: программа для работы с файлами и директориями. Она позволяет копировать, перемещать, удалять, переименовывать файлы и директории, искать файлы по разным критериям, менять атрибуты, составлять списки...

Еще одно сходство между PowerPro и Хxcopy: все пользователи PowerPro то ли жалуются, то ли, скорее, тайно гордятся сложностью конфигурирования программы, настройки под конкретную операцию. То же можно сказать и про Хxcopy. Перепробовать ее во всех режимах, при всех сочетаниях ключей, наверное, вообще невозможно. Количество ключей точному подсчету не поддается, по моей оценке - около двухсот. Дело в том, что некоторые являются взаимоисключающими, а некоторые имеют настолько много модификаций, что становится непонятно - считать их разными ключами или разновидностями одного?

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

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

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

Второй недостаток - трудоемкость настройки. Документация по Ххcopy достаточно подробна, но, как уже говорилось, чтобы рассмотреть все возможные сочетания ключей, их взаимодействие, конфликты и приоритеты во всех возможных ситуациях, авторам программы пришлось бы писать многотомный справочник. Сравнивая трудность настройки PowerPro и Xxcopy, понимаешь, что в первом случае к твоим услугам - tooltips, контекстная помощь, файлы в форматах chm и doc, а во втором - только длинный текстовый файл, который, кстати, надо еще из программы вытащить с помощью ключей /help или /helpa, кому как удобнее. Правда, в последних версиях chm-файл тоже появился.

Наконец, третий недостаток - сложности работы с русскими именами файлов и директорий. Дважды в жизни мне пришлось столкнуться с этой проблемой и я нашел как минимум два решения. Точнее говоря, Xxcopy не работает с русскими именами напрямую, в лоб: попытавшись скопировать файл с таким именем, получим в результате кракозябры. Приходится искать обходные пути, а обширные возможности программы дают, соответственно, многочисленные способы обхода ее ограничений!

В версии 2.97.3 частичная поддержка unicode все-таки появилась. Чтобы заставить Xxcopy скопировать, например, директорию с русским названием, заносим путь к ней в текстовый файл и подцепляем этот файл ключом /cf. А составлять списки русскоязычных директорий (что мне приходится делать очень часто посредством своих скриптов) Xxcopy умела издревле.

Итак, что же еще может Ххcopy? Приведу лишь несколько примеров.

Пример первый. Пусть стоит задача - найти в заданной директории и дочерних файлы определенного, скажем, нулевого размера, и сохранить список в файл-отчет. Для использования возможностей Ххcopy пишем batch-файл (в просторечии - "батник") следующего содержания:

xxcopy.exe %1 /SZ:0 /s /L /foимя_файла-отчета

Здесь %1 - параметр батника, передаваемый ему любым способом - через командную строку, через параметр %Т кнопки Total Commander, через скрипт, через другой батник. Смысл параметра - путь, в котором (и ниже) ищутся нулевые файлы.

А слабо вам найти нулевые файлы во всех поддиректориях, кроме десятка, список которых находится в файле?! В приведенной выше команде мы просто подключаем файл-список ключом /ex. И все.

Пример второй. Однажды мне понадобилось скопировать структуру директорий, то есть создать в заданном месте иерархическое дерево директорий от определенной директории и ниже. Иными словами, скопировать только пустые директории, без файлов. Можно решить эту задачу с помощью Total Commander или скрипта PowerPro? Можно. Только извините, считать количество нажатий клавиш или щелчков крысы я не буду.

С помощью Xxcopy нужна всего одна строка:

xxcopy.exe %1 %2 /T

Этот батник я вызываю из Total Commander, передавая параметры %P %T.

Наконец, пример третий. Данная задача встает передо мной весьма часто: удалить все пустые, то есть не содержащие файлов, директории. Вот решение:

xxcopy.exe %1 /rmdir /x*.* /yy

Здесь рассмотрены наиболее простые примеры, сводящиеся к одному-единственному вызову Xxcopy. Обратим внимание также, что во всех рассмотренных примерах не производилось того, ради чего, казалось бы, программа Xxcopy и создана - копирования файлов. Чтобы читателю жизнь с Xxcopy не казалась сахаром, приведу отрывок из батника, который производит резервное копирование (бэкап) моих настроек, в данном случае - батников, списков исключений (*.exc) и включений (*.swi) самой Xxcopy:


xxcopy.exe c:\utils\xxcopy\*.bat %1\c\utils\Xxcopy\
/in*.exc /in*.swi /a0 /bi /c0 /er /ff /h /ks /q3 /r
/s /yy /zy /pb%3 /oaCritical.rep /foXXcopy.lst

if errorlevel 5 ERmode.bat 5 XXcopyFiles
if errorlevel 4 ERmode.bat 4 XXcopyFiles
if errorlevel 2 ERmode.bat 2 XXcopyFiles
if not -%2==-all goto Reports

Здесь %1 - путь-приемник, %2 - параметр батника, позволяющий копировать не все настройки, а лишь определенные, наконец, %3 задает режим отображения progress bar'а при копировании.

Знатокам батников видно, что после вызова анализируется код выхода и, в случае ошибки, управление передается другому батнику, который эту ошибку обрабатывает, вновь передает управление... Анализируются лишь три значения кода выхода, а всего их у Xxcopy знаете сколько? Двести пятьдесят пять!

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

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

Почему я поместил статью про Xxcopy именно на сайте, посвященном программам Total Commander и PowerPro? Во-первых, Xxcopy идеально подходит для вызова из Total Commander, передающего ей параметр %Р и подобные ему. Во-вторых, Total Commander и Xxcopy нацелены прежде всего (хотя обе не только) на работу с файлами и директориями. В-третьих, между PowerPro и Xxcopy прослеживаются определенные, пусть и несколько отвлеченные, аналогии, с которых я начал свой опус. Наконец, в-четвертых, язык батников - это, по сути своей, тоже скриптовый язык, только в роли программы-интерпретатора выступает сама операционная система.

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


Знакомство с bat-файлами

Предисловие

Статья, предлагаемая вниманию читателя, была мной опубликована в 2000 г. в рассылке службы "CityCat". Рассылку под названием "Программирование для начинающих" вел мой приятель, по просьбе которого я и написал данную статью для темы "Программирование под DOS" или типа того. В целях чистоты эксперимента я не стал менять в ней ни единой запятой. Поэтому попрошу читателя делать поправку на следующие три факта:

Вначале о терминологии. Слово «batch» в переводе с английского означает «партия», «пакет», «группа». По поводу перевода термина «batch file» в литературе существует забавный, но временами вводящий в заблуждение разнобой. Приведем наиболее распространенные разночтения: «пакетный файл», «командный файл», «пакетный командный файл», «файл пакетной обработки». Все эти термины представляются неудачными, ибо слово «пакетный» может быть спутано с «пакетом прикладных программ», а «командный» – с СОМ-файлом. Есть и жаргонные синонимы – «бэтч» и «батник» (однажды я даже слышал «ватник»). Это уже лучше, но слишком уж приблатненно. Поэтому будем пользоваться нейтральным и однозначным термином ВАТ-файл.
Зачем же он нужен?

 

Пример первый. Файл AUTOEXEC.BAT

Если вам приходилось устанавливать DOS, то вы не могли не заметить, что вне зависимости от вашего желания DOS создает на C:\ файлы AUTOEXEC.BAT и CONFIG.SYS (это одна из функций некоторых инсталляторов). Второй из них мы обсуждать не будем, сосредоточившись на первом. Его название составлено из начал английских слов «automatic execution», то есть «автоматическое исполнение». Он содержит команды, выполняемые при каждом включении или перезагрузке компьютера. В частности, входя в DOS, вы захотите, чтобы у вас были активны, например:

Это разумный минимум. Кроме того, есть бесконечное количество других услуг, из которых вам наверняка (или, по крайней мере, почти наверняка) потребуется следующее: Разумеется, все это можно сделать и вручную, вводя соответствующие команды традиционным способом. Но: И появляется шальная мысль: «А нельзя ли сделать так, чтобы это выполнялось автоматически?». Разумеется, можно. Ведь не вы один такой ленивый. Поэтому другие ленивые люди и придумали ВАТ-файлы вообще и AUTOEXEC.BAT в частности. Отладив его один-единственный раз, можно после нажатия кнопки включения компьютера пойти налить себе чаю, а вернувшись, увидеть родные сине-белые панели папаши Нортона и в середине – красненький прямоугольник мышиного курсора. И можно не сомневаться – русские тексты читабельны, сидюк виден. А все он, батюшка-кормилец, AUTOEXEC.BAT.
В те благословенные времена, когда я работал под DOS, я решил, что не реже чем один раз в месяц нужно выполнять следующие действия: 1) полная проверка на вирусы; 2) дефрагментация диска; 3) сканирование оного Disk Doctor'ом. Так вот, каждый раз при загрузке на экране появлялась информация о дате последнего из этих действий, и, если это было раньше чем месяц назад, соответствующее сообщение назойливо мигало и предлагало начать проверку немедленно.
Кстати, если DOS при загрузке не находит файла AUTOEXEC.BAT, ничего трагичного не случается. По умолчанию отрабатываются команды DATE и TIME, после чего DOS ожидает команды.

 

Пример второй. Антивирусы

Каждый раз, проверяя свой агрегат на зловредные вирусы, я запускал Aidstest Лозинского и DrWeb Данилова. Вот какие командные строки для этого требовались:

C:\UTILS\AIDS\AIDSTEST\AIDSTEST.EXE C: /F /PAIDSHDD.REP /Q /B /X

C:\UTILS\AIDS\DRWEB\DRWEB.EXE C: /CL /CUP /DL /HI /MS /NI /OK /QU /RP /RV /SD /SO /TB /WF

Запомнили? Мне-то еще ничего, я раз в месяц проверял, а если от кого нужда или горький опыт требует это делать еженедельно? Ежедневно? Невольно подумаешь: «Черт с ними, с вирусами, авось пронесет, а тут такой роман писать». Вы спросите, как я это вытерпел? Да никак. Один раз потратил полчаса, написал ВАТ-файл и с тех пор горя не знал. Запустишь его и занимаешься своими делами.

 

Пример третий. Резервное копирование

Ничто не вечно под луной. Даже сверхустойчивая DOS иногда падает. На жестких дисках появляются плохие сектора, и по закону подлости на самых ответственных участках. Выходят из строя контроллеры. Случайно (или по воле друзей и сослуживцев с избыточным чувством юмора) затираются системные файлы. Или их съедает вирус, против которых Лозинский, Данилов и Касперский еще не успели написать противоядие... Короче, безопасности никогда не бывает слишком много. А посему важные файлы хорошо бы иметь где-то еще, кроме жесткого диска: на дискете, на другом компьютере, на ZIP'е, а еще лучше – везде, где только возможно. Я, например, к числу важных файлов относил следующие:
Мало того, что они периодически обновляются. Они еще и разбросаны по всему диску. Надо их отовсюду извлечь и скопировать в одно место. Причем только если файл со времени последнего резервного копирования обновлялся. Потом вставить дискеты и «спасти». Вручную – опять же, долго, утомительно и тоскливо. ВАТ-файл делает все сам, разве что дискеты не вставляет.

 

Пример четвертый. Групповое переименование

Накапливаются текстовые файлы. Я их нумеровал: 01.TXT, 02.TXT, 03.TXT... Потом дело дошло до 99.TXT. Что делать? Ясно, что. Переименовать файлы следующим образом: 01.TXT станет 001.TXT, 02.TXT станет 002.TXT, и все дела. А теперь попробуйте-ка сделать это через команду ren. Разумеется, по маске, чтобы одной командой все файлы разом. Получилось? Если да, то напишите, как. Признаюсь, у меня не получилось. Из командной строки. А в ВАТ-файле для этого потребовалась одна-единственная команда. Привычное потрескивание винчестера, мелькание текста на экране, и пожалуйста – цель достигнута.

Итак, резюме таково: ВАТ-файл

По-моему, рекламы достаточно.


Законы ВАТ-файлов

Закон Первый. ВАТ-файл – это программа на алгоритмическом языке DOS;

Закон Второй. ВАТ-файл может принести вреда больше, чем пользы;

Закон Третий. ВАТ-файл не умеет больше того, что умеет DOS.

Комментарии:
  1. Можно утверждать, что язык ВАТ-файлов – самый примитивный из существующих. Переменные? Да, они есть, но уж с очень корявыми именами. Циклы? Всего один, и то с весьма скудными возможностями. Ветвление? Есть, но опять же, упрощено до крайности.

  2. Если вы пишете программу на Паскале, то худшее, что вас может постичь – потеряете время. С ВАТ-файлом все серьезнее. Достаточно выполнить ВАТ-файл с командой del C:\COMMAND.COM – и очень крупные неприятности вам гарантированы. Поэтому до тех пор, пока вы не почувствовали себя в ВАТ-файлах, как рыба в воде, не покушайтесь на святое. Сделайте следующее:
  3. Как уже говорилось, все можно делать и из командной строки. Вопрос – сколько это займет времени, сколько раз вы за это время зевнете и сколько при этом допустите ошибок. Суть Третьего Закона в том, что ВАТ-файл – не волшебник, а помощник.

Как вы уже, очевидно, догадались, простейший ВАТ-файл содержит команды DOS, по одной на строку. Создадим файл FIRST.BAT (например, в Нортоне для этого надо нажать Shift-F4) и напишем в него:

ver
dir

Сохраним и выйдем (F2, затем F10). Вначале те же команды DOS (ver и dir) последовательно выполним из командной строки, а затем запустим на выполнение ВАТ-файл. Заметили разницу? Правильно, ВАТ-файл выполняет команды подряд, без паузы. Впрочем, паузу тоже можно организовать. Но об этом позже.
Кстати, как выполнить ВАТ-файл? Так же, как любой другой исполняемый файл DOS. В Нортоне либо наводим на него курсор и нажимаем Enter, либо дважды щелкаем мышью. Из командной строки набираем либо полное имя (FIRST.BAT) либо только имя без расширения (FIRST) и опять же нажимаем Enter. Но в последнем случае надо помнить одно важное правило:

При указании только имени (без расширения) одноименные исполняемые файлы DOS запускаются в следующем приоритетном порядке: COM EXE BAT

То есть расширение ВАТ для DOS имеет совершенно особый смысл, и неспроста. Если в DOS вам не хватает команд, внешних и внутренних, пишите свою «команду DOS» – это и будет ваш ВАТ-файл.
Итак, первый опыт исполнения простейшего ВАТ-файла показал, что нет никакой существенной разницы между исполнением команд DOS и исполнением ВАТ-файла, эти команды содержащего. Вот вам и поле для экспериментов. Например, не выходя за пределы полигона, попробуйте следующее:

  1. Создать директорию ONE;
  2. Скопировать туда файл WOLF.TXT (допустим, что он у нас есть);
  3. Перейти в эту директорию и просмотреть ее содержимое;
  4. Вернуться;
  5. Стереть файл WOLF.TXT;
  6. Стереть директорию ONE;
  7. Убедиться, что мы ее действительно стерли.

Попробуйте проделать все это, не заглядывая дальше, а потом проверьте.

md one
copy wolf.txt one
cd one
dir
cd..
del one\wolf.txt
rd one
dir

Разумеется, ваш текст может слегка отличаться от моего. Например, вторая строка может с тем же успехом иметь следующий вид:

copy wolf.txt c:\test\one
copy wolf.txt c:\test\one\*.*

Суть не в форме, а в содержании. Раз вы выполнили поставленную задачу, то детали большого значения не имеют. Например, можно долго и достаточно продуктивно рассуждать об относительном (ONE) и абсолютном (C:\TEST\ONE) указании пути. Но это обсуждение имеет отношение уже не к теме ВАТ-файлов, а к теме DOS вообще.


Теперь пора перейти к тем возможностям ВАТ-файла, которые не существуют в DOS как таковой, и которые придают ВАТ-файлу почти безграничные возможности. Будь на то моя воля, я бы каждый учебник по программированию начинал с самого важного оператора – оператора комментария. Эти операторы служат двум главным целям: 1) снабжение своего детища пояснениями; 2) временное исключение из обработки участков программы. Для последней цели существует даже специальный термин: «закомментировать». Итак, формат комментария таков:

rem Любой текст

Текст не должен содержать символы > («больше»), < («меньше») и | («конвейер»).
Как вы уже заметили (из опыта исполнения FIRST.BAT), каждая строка ВАТ-файла вначале выводится на экран, а затем выполняется. Хорошо это или плохо? Для отладки – хорошо, поскольку всегда видно, что в данный момент происходит. Для выполнения – плохо, ибо экран забивается лишней информацией, которая мешает увидеть информацию полезную. То есть неплохо было бы научиться управлять выводом: когда надо – включать, когда не надо – отключать. Для этого используется команда echo.
Уважаемые любители английского языка и счастливые обладатели оксфордского произношения! Если вы будете говорить слово «echo» так, как оно в действительности произносится, вас просто не поймут. Посему прикиньтесь посконным рязанским мужичком и произносите это слово как «эхо». На программерском жаргоне словосочетание «выводить информацию» подчас обозначается термином «эхировать». И в этом можно усмотреть особый смысл. Строка ВАТ-файла и ее исполнение – это ни что иное, как наше «Ау!» и его эхо. Клич есть всегда, а отклик может быть, а может и не быть.
Итак, команда echo существует в пяти форматах:

  1. echo Текст
  2. echo on
  3. echo off
  4. echo
  5. echo.

А теперь – разъяснения:

  1. Команда выводит текст на экран. Разумеется, выводится только текст, без самого слова echo и пробела, который для данного формата обязателен. Правда, текст не должен содержать символы > («больше»), < («меньше») и | («конвейер»). Точнее говоря, их можно использовать, лишь твердо понимая, зачем вы это делаете. Кроме того, лучше воздержаться от использования символа %. Потом станет ясно, почему.
  2. Вывод на экран включается (режим по умолчанию).
  3. Вывод на экран выключается (подавляется).
  4. Выводит информацию о текущем состоянии режима эха. Исполнение этой команды приводит к одному из следующих сообщений:
    ECHO is on
    ECHO is off
    Единственное, что остается загадкой – практический смысл этого формата.
  5. Вывод на экран пустой строки. Того же результата можно достичь, введя вместо точки пробел и символ с кодом 255. Но это по всем признакам менее удобно.

Итак, если мы хотим создать «молчаливый» ВАТ-файл, то первой его строкой должна быть такая:

echo off

Создадим ВАТ-файл следующего содержания:

echo off
echo Some text

Его выполнение даст следующее:

echo off
Some text

Проведем разбор полетов. Вторая строка исполнена так, как нам хотелось: выведен только текст, а сама команда осталась «за кадром». Значит, первая строка сработала верно, подавив вывод. Но сама она на экран вывелась. Почему? Да все потому же: любая строка вначале эхируется (если эхо включено), а лишь затем выполняется. А эхо включено по умолчанию. Так что же, нельзя «заглушить» вывод строки echo off? Можно. Начиная с третьей версии DOS, в ВАТ-файлах введено такое правило:

Любая строка, начинающаяся с символа @, не выводится на экран, вне зависимости от текущего режима.

Иными словами, команда echo off обеспечивает подавление глобальное, а символ @ – локальное. Обрадовавшись, исправим наш ВАТ-файл и получим вот что:

@echo off
echo Some text

Теперь его исполнение полностью соответствует нашему желанию:

Some text

Если собрать с самых разных компьютеров 100 ВАТ-файлов, то можно биться об заклад, что в 95 из них первая строка будет именно такая: @echo off. Остальные же 5 наверняка находятся в стадии разработки и вывод умышленно включен для целей отладки.
Это вовсе не значит, что с @ должна начинаться только строка echo off и только первая. Рассмотрим два ВАТ-файла и попробуем вначале проследить, как они будут исполняться:

@echo off
echo on
echo Hello everybody! Here it is
@ver
@echo Good bye.

@echo off
echo on
echo Hello everybody! Here it is
@echo off
ver
echo Good bye.

Кстати, в свете Второго Закона любой ВАТ-файл полезно вначале выполнить умозрительно, без набивки. Мало того, что это спасет вас от необратимых катастроф. Это позволит лучше постичь логику процесса. Так что, заметили разницу в выполнении двух вышеприведенных ВАТ- файлов? И я нет.
А можно ли подавить вывод на экран не самой команды, а результатов ее выполнения? Многие справочники этот вопрос стыдливо замалчивают. Впрочем, их можно понять. Подавление результата выполнения команды превращает ВАТ-файл в своего рода «черный ящик»: что-то делает, а что – неизвестно. Однако я этим приемом частенько пользуюсь. Итак, результат выполнения команды можно направить на любое устройство командой

ctty устройство

Например, для вывода списка файлов текущей директории на принтер надо написать

ctty prn
dir /w

Но наиболее часто используются устройства con и nul. Устройство «con» – это консоль, попросту экран. Устройство «nul» – нулевое, то есть отсутствие какого-либо устройства. По умолчанию, разумеется, предполагается вывод на экран. Но зачем это может пригодиться? Однажды я написал достаточно большой ВАТ-файл, одной из задач которого было архивирование с паролем, вводимым из командной строки. Само собой, демонстрировать этот пароль кому-либо у меня не было никакого желания. И если момент ввода пароля в командную строку я выбирал сам, то гарантировать, что кто-то не взглянет на экран как раз в момент выполнения команды архивирования, я не мог. Выход? Направить вывод на нулевое устройство командой ctty nul, затем заархивировать и уже потом восстановить вывод на консоль командой ctty con.
Заметим, что команды echo и ctty действуют независимо друг от друга. Поэтому можно довести наше сравнение до абсурда – наличие эха при отсутствии звука.
А теперь обратимся к обещанной паузе. Формат команды крайне прост: pause. Попробуйте. Не понравился текст, который команда выдает на экран? У вас ВАТ-файл общается с пользователем по-русски, а тут досадное английское приглашение? Что же, дело поправимо... Догадались?

echo Нажмите любую клавишу
pause > nul

Зачем же символ перенаправления, если команда ctty обходилась без него? Во-первых, она все-таки может его использовать. Попытайтесь это сделать и посмотрите, что выйдет. Во-вторых, перенаправление – это правило, а не исключение. Попробуйте перенаправление с командами ver, dir, date, и вообще теми, которые что-то пишут на экране. Кстати, в качестве устройства могут выступать не только стандартные (con, prn, nul, com1 и другие), но и любой файл. Я этим очень часто пользуюсь. Вообще перенаправление и фильтры – неисчерпаемая тема. Но все это может быть использовано и в командной строке, а мы сейчас обсуждаем команды, специфичные только для ВАТ-файлов.
Команды rem, echo, ctty и pause составляют, так сказать, декоративную сторону ВАТ-файлов. В самом деле, они упрощают и украшают общение файла с пользователем, но к функциональной стороне дела имеют лишь косвенное отношение. Пора перейти к серьезным темам.

Как и при изучении любого языка программирования, где вначале рассматриваются просто операторы, а затем конструкции, мы только сейчас готовы к знакомству с одной из двух (всего двух!) конструкций ВАТ-файлов. Речь идет о ветвлении, иными словами – об условном операторе. Он может существовать в одном из следующих форматов:

  1. if [not] exist имя команда
  2. if [not] параметр1==параметр2 команда
  3. if [not] errorlevel код команда

Квадратные скобки, как обычно, окружают необязательный элемент формата.
Все три условные конструкции объединяет одно – команда исполняется тогда, когда высказывание истинно. В противном случае строка игнорируется и выполняется следующая. Впрочем, что еще можно ждать от условной конструкции в свете Первого Закона ?

  1. Имя файла (или даже директории, правда, с неким ухищрением) понимается в широком смысле: локальное или полное (включая путь) имя конкретного файла, а также маска. Рассмотрим пример. Многие программы создают временные файлы (как правило, с расширениями ТМР, ВАК, OBJ). Эти файлы размножаются, занимают место и мозолят глаз. Полезно время от времени проводить «зачистки». Казалось бы, чего проще:

    del *.tmp

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

    if exist *.tmp del *.tmp

    Ключевое слово not, как нетрудно догадаться, обращает условие, преобразуя истину в ложь и наоборот:

    if not exist *.exe echo Нет ЕХЕ-файлов

  2. Попробуйте догадаться, чего нам не хватает, чтобы воспользоваться этим форматом. Давайте рассуждать логически. Что в DOS может пониматься под параметром? Имя файла (директории), больше ничего. Но если эти параметры заранее известны (являются константами), то теряется смысл их сравнивать. Следовательно, по меньшей мере один из параметров должен быть переменной ( Первый Закон в действии). А откуда взяться переменным? Конечно же, их надо передать файлу. А иначе, как из командной строки, сделать это невозможно. Вот так мы и поняли, что второй формат условной конструкции призван разбираться с ключами ВАТ-файла. Но как именно это делается, мы узнаем чуть позже.
  3. Самый загадочный и в то же время могущественный из форматов. Дело в том, что он нарушает Первый Закон ВАТ-файлов. Но, в конце концов, какое правило без исключений?
    Что же такое errorlevel? Справочники говорят об этом примерно так: «В определенных случаях некоторые программы возвращают число, которое иной раз кое-что и значит» . Англоязычные справочники именуют errorlevel как «exit code» – «код выхода» или «код завершения». То есть некоторые программы при завершении работы записывают в определенную область памяти код (целое неотрицательное число), которое как-то связано с результатом выполнения этих программ. Однако: Нет иного пути извлечения кода выхода программы, кроме третьего формата условной конструкции ВАТ-файла. Не исключено, что существуют для этой цели некие специальные утилиты. Мне такие не встречались. Но даже они не в силах ответить на большинство вопросов.
    Слава богу, существует документация. Цитирую справочник по MS DOS 4.х:
    «Команда FORMAT возвращает следующие коды выхода:
    0 – успешное завершение;
    3 – прервано пользователем (нажатие Ctrl-C);
    4 – фатальная ошибка, отличная от 0, 3 и 5;
    5 – отрицательный ответ на запрос о форматировании жесткого диска»

    Обратите внимание, что ситуация «0», то есть «успех», названа ошибкой. Кроме того, где значения 1 и 2? Вторая цитата нас немного успокоит. Игорь Данилов, документация к антивирусу DrWeb:
    «0 – Вирусы не обнаружены;
    1 – Обнаружены известные вирусы;
    2 – Обнаружены неизвестные вирусы или подозрительные файлы»

    Вот это уже совсем другое дело. О том, как же обрабатывать эти коды, мы поговорим чуть позже.
    В. Э. Фигурнов в своем бестселлере «IBM PC для пользователя» даже приводит список внешних команд DOS, которые возвращают код выхода (Фигурнов его называет «код возврата»), однако не описывает их значения, количество и смысл. Хорошо, если у вас есть документация по DOS, а если нет? Тогда придется изрядно потрудиться, чтобы прояснить это для каждой конкретной программы.

Возникает законный вопрос: «А что если в случае истинности высказывания в условной конструкции надо выполнить не одну, а несколько команд?». Как поступают в этом случае современные языки программирования, нам известно. Но с ВАТ-файлом этот выход, увы, не всегда является наилучшим. От пресловутой команды безусловного перехода (goto) можно и отказаться, но прежде чем сделать это, рассмотрим, как ее применять.
Команда goto должна куда-то посылать... то есть отсылать – к метке. А меткой в ВАТ-файле считается любая строка, начинающаяся с двоеточия.
В одном учебнике было интересное предложение: не использовать команду rem ввиду ее неудобочитаемости, а комментарии оформлять как фиктивные метки, причем для отличия от меток фактических (на которые есть ссылки) после двоеточия писать какой-нибудь определенный символ, скажем, звездочку. Сравните эти два комментария:

rem Это комментарий
:* Это комментарий

Ни в одном учебнике мне не удалось найти четкого описания ограничений на вид метки. К примеру, правильно сработает такая ссылка:

goto (This is a very complicated label!)

:(This is a very complicated label!)

Правда, метка воспринимается только до первого пробела. То есть вышеприведенная метка полностью идентична такой: (This . Кроме того, метки плохо реагируют на ведущий не буквенный и не цифровой символ. Поэтому лучше не рисковать и составлять метки только из букв и цифр.

Настало время разобраться с переменными, которые позволят нам предметно обсуждать второй формат условной конструкции.
Как нам известно, большинство команд DOS, внешних и внутренних, и исполняемых файлов вообще, принимают параметры командной строки (ключи), отделяемые друг от друга пробелами. ВАТ-файлы не являются в этом смысле исключением. В свете того, что ВАТ-файлы являются своего рода процедурами DOS, нетрудно понять, что параметры командной строки суть ни что иное, как фактические параметры, передаваемые процедуре. Им должны соответствовать формальные параметры самой процедуры, то есть ВАТ-файла. Они имеют имена, состоящие из двух символов, из которых первый – символ %, а второй – цифра от 1 до 9. Например, если мы снабжаем имя ВАТ-файла тремя фактическими параметрами, то в самом ВАТ-файле им будут соответствовать формальные параметры %1, %2 и %3. Если формальных параметров больше, чем фактических, остальным присваиваются значения «пустая строка». Если фактических больше, то лишние игнорируются.
Пусть нам необходимо сархивировать содержимое некоторой директории в многотомный архив для копирования на дискеты. ВАТ- файлу нужно передать следующие фактические параметры:

  1. Имя директории, содержащей файлы;
  2. Имя архива;
  3. Размер тома.
Этим параметрам будут автоматически присвоены имена от %1 до %3, соответственно. Осталось лишь написать ВАТ-файл, использующий эти формальные параметры и названный SECOND.BAT.

@echo off 1
cls 2
echo Параметры ВАТ-файла %0: 3
echo %0 директория архив размер 4
echo. 5
echo где: 6
echo директория - имя директории-источника (без замыкающего символа \); 7
echo. 8
echo архив - имя архива-назначения (без замыкающей точки); 9
echo. 10
echo размер - размер тома (может быть 1440 или 1200). 11
echo. 12
echo Нажмите любую клавишу для продолжения или Ctrl-C (Ctrl-Break) для прерывания... 13
echo. 14
pause > nul 15
 
if -%1==- goto NoParam 16
if -%2==- goto NoParam 17
if -%3==- goto NoParam 18
 
if not exist %1\nul goto WrongParam 19
if -%3==-1440 goto Continue 20
if -%3==-1200 goto Continue 21
goto WrongParam 22
 
:Continue 23
arj a %1\%2 -y -v%3 %1\*.* 24
if errorlevel 1 goto ARJerror 25
echo Архивирование завершено успешно. 26
echo Вставьте дискету и нажмите любую клавишу... 27
pause > nul 28
copy %1\%2.arj a: 29
if exist %1\%2.a01 echo Остальные файлы скопируйте самостоятельно. 30
goto End 31
 
:ARJerror 32
echo Ошибка при архивировании. 33
goto TryAgain 34
 
:WrongParam 35
echo Неверные параметры. 36
goto TryAgain 37
 
:NoParam 38
echo Не хватает параметра. 39
 
:TryAgain 40
echo Будьте внимательны и попробуйте еще раз. 41
 
:End 42

Разумеется, строки пронумерованы лишь для удобства разбора.
[1] Как мы уже отмечали, это почти стандартное начало любого ВАТ-файла не дает ему быть чрезмерно болтливым.
[2] Команда cls наверняка не вызовет вопросов у тех, кто хоть немного программировал. Для остальных после паузы сообщим: команда cls очищает экран и устанавливает курсор в его левый верхний угол.
[3] Формальные параметры можно использовать не только в условных конструкциях, но и вообще где угодно. Параметр %0 отличается от остальных тем, что присутствует в любом ВАТ-файле. Дело в том, что нумерация параметров командной строки, разделенных пробелами, начинается с 0, как и положено. Просто нулевым параметром в таком случае неизбежно является имя самого ВАТ-файла, причем в той форме, в которой реально в этой строке фигурировало. Поясним. Мы работаем в Нортоне и запускаем наш ВАТ-файл на выполнение наиболее экономным образом: наводим на его имя курсор и нажимаем Ctrl-Enter. В командной строке появляется:

second.bat

Затем вручную вводим параметры и окончательно получаем:

second.bat c:\test two 1440

Тогда при отработке строки [3] на экране появится:

Параметры ВАТ-файла second.bat:

потому что именно так (в строчном регистре и с расширением) выглядел при запуске первый параметр (%0) командной строки.
Если же командная строка имела вид

SECOND c:\test two 1440

то и результат будет соответствующий:

Параметры ВАТ-файла SECOND:

Как мы понимаем, это не более чем косметика, поскольку DOS нечувствительна к регистру.
[3] ... [15] : Первый эшелон "защиты от дурака", то есть от умышленно неправильных или ошибочных действий пользователя. К сожалению, в узких рамках примитивного языка ВАТ-файла обеспечить полноценную защиту от дурака очень трудно, если вообще возможно, но... надо стараться. Ведь если в языке высокого уровня защита от дурака - зачастую требование удобства или хорошего тона, а не безопасности, то Второй Закон ВАТ-файлов требует, чтобы не то чтобы разрушительные, но даже непредсказуемые последствия ошибки были сведены к минимуму.
Причем это необходимо, даже если ВАТ-файл не предполагается давать кому-либо другому и единственным пользователем может быть лишь сам автор. Даже спустя месяц уже самому трудно вспомнить, в какой именно последовательности какие параметры надо указывать. Начальный этап выполнения позволяет пользователю сравнить подробное толкование параметров с тем, что он только что написал. Увидев, что совершена ошибка, надо нажать упомянутые клавиши (подсказка об очевидном - второй эшелон защиты), в противном случае продолжить выполнение.
Кстати, с точки зрения защиты от дурака команда cls в строке [2] не совсем корректна. Ведь теперь, когда экран очищен, пользователь не видит своей команды и ее параметров. Хорошо было бы, чтобы сравнение того, что есть, с тем, что должно быть, проводилось весомо, грубо и зримо. Так что лучше команду cls поместить после строки [15] . Еще, строке [7] можно придать вид:

echo директория - имя директории-источника (без замыкающего символа \). Вы задали: %1

И то же для строк [9] и [11] . Тогда, вообще говоря, строку [2] можно оставить в покое.
[16] ... [18] : Третий эшелон. Пользователю не верят на слово и проверяют истинное наличие параметров. Пока только наличие. Если параметров нет вовсе, на это среагирует строка [16] . Если он один, об этом узнает строка [17] . И, наконец, об отсутствии третьего параметра станет ясно после отработки строки [18]
. Разумеется, можно организовать четвертый эшелон защиты, предусмотрев отдельную обработку для каждого из случаев. Мы пошли по более простому пути, объединив все три случая. Если число параметров меньше трех, на экран будет выдано:

Не хватает параметра.
Будьте внимательны и попробуйте еще раз.

После этого выполнение ВАТ-файла завершится. Как аварийно прервать его выполнение, мы уже знаем. Штатное завершение выполнения возможно только по достижении конца файла. И, если первая строка почти всегда имеет вид @echo off, то последней разумно делать строку

:End

Тогда для штатного завершения работы ВАТ-файла можно использовать одну и ту же команду

goto End

Зачем стоят минусы перед именами параметров во втором формате? Слово В. Э. Фигурнову: "Сравнение второго параметра командного файла со строкой SSS не следует делать так: if %2==SSS... Ведь если в командном файле меньше двух параметров, то символы %2 будут замещены пустой строкой, и при выполнении команды возникнет ошибка. Правильное сравнение выглядит так: if -%2==-SSS... Оно годится в любом случае". Я даже не пытался поставить под сомнение слова Мэтра. И ни разу не пожалел об этом.
[19] : Четвертый эшелон защиты. Проверяется наличие заданной директории, в нашем случае C:\TEST. Напрямую ключевое слово exist относится только к файлам, но не к директориям, поэтому приходится использовать маленькие хитрости. Даже если директория пуста, она содержит устройство nul (нулевое, фиктивное, отсутствующее устройство). И лишь если директория %1 не существует, высказывание станет ложным и оператор goto отошлет выполнение к метке WrongParam.
[20] ... [21] : Пятый эшелон. Многотомное архивирование делается чаще всего для копирования на дискеты. Поэтому в архиватор ARJ "зашиты" стандартные форматы 360 кб, 720 кб, 1.2 Мб и 1.44 Мб. Первые два формата остались разве что в воспоминаниях о нашей розовой юности. Если быть до конца честным, то и "хайовые" пятидюймовки так и не успели достичь популярности, а оказались вытесненными трехдюймовками. Но ведь мы просто учимся, а эта благая цель оправдывает легкие прегрешения против действительности.
Какой бы параметр ни был задан - 1200 или 1440, отработается оператор goto и выполнение продолжится с метки Continue. И только если оба высказывания окажутся ложными, выполнение ВАТ-файла прервется - архивирование невозможно. Цепочку условных конструкций, аналогичную строкам [20] ... [23] , разумно приводить всегда, если параметр может принимать одно значение из конечного множества заранее известных. Например, параметры %1 и %2 этому требованию не удовлетворяют.
[24] : Кажется, мы сделали почти все, чтобы ошибочные параметры не пробились сквозь глубоко эшелонированную защиту от дурака. Тем досаднее будет, если архиватор ARJ, что называется, "не прописан". Разумеется, проще всего указать его полное имя. Но мы рассмотрим другой путь.
Если набрать в командной строке DOS произвольную комбинацию символов и нажать Enter, то DOS будет пытаться интерпретировать это как команду и выполнить ее, а для этого искать комбинацию:

  1. Вначале среди своих внутренних команд;
  2. Затем среди СОМ-файлов в текущей директории;
  3. Затем последовательно среди ЕХЕ- и ВАТ-файлов - там же;
  4. Наконец в том же приоритетном порядке (СОМ, ЕХЕ, ВАТ) среди всех директорий, указанных в значении переменной окружения %РАТН%;
  5. И только если последний этап завершится неудачей, DOS выдаст сообщение Bad command or file name.
Что же такое переменная %РАТН%? Заглянем в наш AUTOEXEC.BAT. Скорее всего, он будет выглядеть так:

@echo off
prompt $p$g
path c:\;c:\dos
c:\dos\mscdex /d:mscd000
c:\utils\rk.com
c:\utils\mmouse.com
c:\nc\nc.exe

Вторая строка устанавливает вид "приглашения DOS". Оно прописывается по умолчанию и, на мой взгляд, весьма разумному. Изучение других видов приглашений выходит за рамки данного исследования. Четвертая и последующие строки загружают: драйвер CD-ROM, русификатор, драйвер мыши и Нортон соответственно. Дело не в них, а в команде РАТН. Там-то и перечислены те самые "избранные" директории, где ищутся командные файлы с неуказанными путем и расширением. Разумно было бы включить в число "избранных" те директории, где лежат архиваторы, чтобы, набрав только arj, мы могли бы получить краткую справку о возможностях этой программы.
Пусть файл ARJ.EXE находится в C:\ARJ. Можно, конечно, изменить AUTOEXEC.BAT, чтобы третья строка имела вид

path c:\;c:\dos;c:\arj

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

path=%path%;c:\arj

Эта команда добавит путь C:\ARJ к списку "избранных", оставив остальные нетронутыми и даже не покусившись на их приоритет относительно c:\arj. Теперь можно быть уверенным, что файл ARJ.EXE будет найден и без указания его полного имени. Правда, после перезагрузки новый путь будет "забыт", а при исполнении SECOND.BAT - вновь "вспомнен".
[25] : В документации к архиватору ARJ перечислены все возможные коды выхода и растолкован их смысл. Значение 0, как обычно, соответствует отсутствию ошибок, а вот коды с 1 до 12 возвращаются в случае ошибки (для каждой - свой код). Мы вновь упростим ситуацию и будем рассматривать только два случая: "ошибка есть" и "ошибки нет". Дело в том, что высказывание "errorlevel число" идентично высказыванию "код выхода БОЛЬШЕ ИЛИ РАВЕН числу". Поэтому:

* Количество конструкций if errorlevel... должно равняться количеству ненулевых значений кода выхода;
* Коды выхода оцениваются строго в НИСХОДЯЩЕМ порядке.

Строка [25] , таким образом, будет отработана, если код ошибки больше или равен 1, то есть при наличии все равно какой ошибки. Мы умышленно нарушили первое из правил, лишив себя возможности узнать причину ошибки, но второе правило соблюли.
Высказывание будет ложно тогда и только тогда, когда архивирование прошло успешно, о чем и уведомляет строка [26] .
[27] ... [29] : Копирование файла на дискету. Раз архивирование свершилось, в заданной директории наверняка существует файл %2.ARJ, то есть, в нашем случае, TWO.ARJ. Что же касается второго тома (TWO.A01) и всех последующих, то их существование уже зависит от суммарного объема файлов. Отчасти это предусматривает строка [30] .
Итак, мы завершили более чем подробный анализ ВАТ-файла. Осталось совсем немного. Вот пример файла, проводящего проверку диска на вирус с помощью DrWeb:

@echo off
drweb c: /cl /nm
if errorlevel 2 goto NewVir
if errorlevel 1 goto Vir
echo Вирусы не обнаружены
goto End

:Vir
echo Обнаружен известный вирус
pause
goto End
:NewVir
echo Подозрение на неизвестный вирус
pause

:End

Мы уже цитировали комментарий И. Данилова к своему детищу. Данный ВАТ-файл демонстрирует последовательность обработки кодов выхода: строго в нисходящем порядке!

Последней темой станет конструкция цикла. Формат ее таков:

for %%буква in (парам1 парам2 [парам3]...) do команда

Цикл работает следующим образом. Переменной %%буква присваивается значение парам1, после чего выполняется команда. Последняя должна зависеть от переменной %%буква, в противном случае цикл теряет смысл. Затем то же происходит для парам2 и так далее, пока список в скобках не будет исчерпан.
Рассмотрим примеры.
Цикл удаляет из текущей директории файлы с расширениями TMP, OBJ, BAK. Проверка на существование этих файлов не производится:

for %%b in (tmp obj bak) do del *.%%b

Цикл переименовывает файлы 01.ТХТ, 02.ТХТ ... 99.ТХТ и THREE.TXT в 001.ТХТ, 002.ТХТ ... 099.ТХТ и 0THREE.TXT соответственно, иными словами, дописывает символ 0 в начало имени:

for %%a in (*.txt) do ren %%a 0%%a

Цикл копирует пять первых томов, созданных архиватором RAR, из директории C:\TEST в директорию, заданную первым параметром ВАТ-файла:

for %%c in (ar 00 01 02 03) do copy c:\test\*.r%%c %1

Может показаться, что количество параметров ВАТ-файла не должно превышать девяти. В самом деле, ведь они снабжаются именами %1...%9. Однако в действительности ВАТ-файл не может обрабатывать более девяти параметров ОДНОВРЕМЕННО. Согласитесь, это не одно и то же.
Мне просто страшно представить себе ВАТ-файл, которому может потребоваться 10 и более формальных параметров. Мало того, что мне самому не приходилось обрабатывать более пяти. Даже среди ВАТ-файлов, написанных другими, мне не встречались такие монстры.
Итак, вообразим невообразимое. Анализ алгоритма показывает, что ВАТ-файл, который вы намереваетесь сваять, потребует 16 (для примера) параметров. Назовем его THIRD.BAT. Прежде всего убедитесь, что одновременно (в пределах одной команды) не потребуется более девяти формальных параметров. Если нет, придется упростить алгоритм, например, путем разбиения этой команды на несколько. Если да, то проблему можно решить. Прежде всего нужно расположить параметры в "порядке надобности". Что это такое?
Вернемся к файлу SECOND.BAT и каждому параметру поставим в соответствие номер строки, где этот параметр упоминается последний раз. Получится вот что:
%0: [4]
%1: [30]
%2: [30]
%3: [24]
При анализе надо учитывать, что благодаря команде goto ВАТ-файл не всегда выполняется строго сверху вниз, поэтому анализ может оказаться весьма нелегким делом, особенно для больших сложных алгоритмов, а наш гипотетический файл THIRD.BAT, судя по всему, именно таков. Анализ файла SECOND.BAT показывает, что он по сути заканчивается на строке [31] , а далее идут подпрограммы, информирующие пользователя об ошибке и параметров не содержащие. Поэтому приведенные выше результаты можно считать верными.
Параметры следует расположить в порядке возрастания номеров строк, где параметр упоминается последний раз. То есть, формально говоря, мы должны были поставить размер тома первым параметром (%1). Но ведь если число параметров не превышает девяти, то надобность в таком анализе отпадает и параметры можно располагать согласно здравому смыслу. Мы так и сделали. Вначале нужно найти заданную директорию (%1), а затем создать архив (%2) заданного объема (%3). Если файлы занимают небольшой объем, то %3 вообще не потребуется.
Однако для THIRD.BAT все может оказаться сложнее. Вначале пронумеруйте параметры произвольным образом, составьте алгоритм и сопоставьте параметры с номерами строк последнего упоминания. Осталось лишь расположить параметры по возрастанию этих номеров и затем перенумеровать. Это и будет искомый порядок надобности.
В начале выполнения ВАТ-файла у нас доступны параметры %0...%9, остальные 7 параметров ВАТ-файл пока "не видит". Как только потребуется параметр, следующий после %9, нужно дать команду shift. В переводе это означает "сдвиг", а именно: номер каждого параметра, начиная с %1, уменьшается на единицу, а параметр %0 становится недоступным. То есть после выдачи команды shift мы уже не сможем манипулировать именем THIRD.BAT, но зато увидим параметр, следующий после %9. Представьте себе окно шириной в 10 параметров. Командная строка имеет вид:

ВАТ-файл парам1 парам2 ... парам16

Изначально окно занимает крайнее левое положение. Каждая команда shift сдвигает окно на один параметр вправо. Следовательно, чтобы увидеть парам16 , надо выполнить команду shift... сколько? Правильно, 7 раз. При этом фактическому парам9 будет соответствовать формальный %2, а фактические парам1 ... парам6 окажутся безвозвратно забыты.
Обратим внимание на то, что действие команды shift необратимо, то есть окно умеет двигаться только вправо. Если анализ проведен правильно и, следовательно, параметры располагаются в порядке надобности, то жалеть о сдвиге не придется.

И, напоследок, несколько кратких замечаний, не вошедших в предыдущий текст.


На главную