Windows Script Host для Windows 2000/XP

Андрей Владимирович Попов

Глава 5. Доступ из сценариев к файловой системе

Сценарии WSH позволяют получить полный доступ к файловой системе компьютера, в отличие от JScript- или VBScript-сценариев, внедренных в HTML-страницы, где в зависимости от уровня безопасности, который устанавливается в настройках браузера, те или иные операции могут быть запрещены.

Выполнение основных операций с файловой системой

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

• копировать или перемещать файлы и каталоги;

• удалять файлы и каталоги;

• создавать каталоги;

• создавать или открывать текстовые файлы;

• создавать объекты Drive, Folder и File для доступа к конкретному диску, каталогу или файлу соответственно.

С помощью свойств объектов Drive, Folder и File можно получить детальную информацию о тех элементах файловой системы, с которыми они ассоциированы. Объекты Folder и File также предоставляют методы для манипулирования файлами и каталогами (создание, удаление, копирование, перемещение); эти методы в основном копируют соответствующие методы объекта FileSystemObject.

Кроме этого, имеются три объекта-коллекции: Drives, Folders и Files. Коллекция Drives содержит объекты Drive для всех имеющихся в системе дисков, Folders — объекты Folder для всех подкаталогов заданного каталога, Files — объекты File для всех файлов, находящихся внутри определенного каталога.

Наконец, из сценария можно читать информацию из текстовых файлов и записывать в них данные. Методы для этого предоставляет объект TextStream.

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


Таблица 5.1. Выполнение основных файловых операций

Операция Используемые объекты, свойства и методы
Получение сведений об определенном диске (тип файловой системы,
метка тома, общий объем и количество свободного места и т.д.)
Свойства объекта Drive. Сам объект Drive создается с помощью метода GetDrive объекта FileSystemObject
Получение сведений о заданном каталоге или файле
(дата создания или последнего доступа, размер, атрибуты и т.д.)
Свойства объектов Folder и File. Сами эти объекты создаются с помощью методов GetFolder и GetFile объекта FileSystemObject
Проверка существования определенного диска, каталога или файла Методы DriveExists, FolderExists и FileExists объекта FileSystemObject
Копирование файлов и каталогов Методы CopyFile и CopyFolder объекта FileSystemObject, а также методы File.Сору и Folder.Сору
Перемещение файлов и каталогов Методы MoveFile и MoveFolder объекта FileSystemObject или методы File.Move и Folder.Move
Удаление файлов и каталогов Методы DeleteFile и DeleteFolder объекта FileSystemObject или методы File.Delete и Folder.Delete
Создание каталога Методы FileSystemObject.CreateFolder или Folders.Add
Создание текстового файла Методы FileSystemObject.CreateTextFile или Folder.CreateTextFile
Получение списка всех доступных дисков Коллекция Drives, содержащаяся в свойстве FileSystemObject.Drives
Получение списка всех подкаталогов заданного каталога Коллекция Folders, содержащаяся в свойстве Folder.SubFolders
Получение списка всех файлов заданного каталога Коллекция Files, содержащаяся в свойстве Folder.Files
Открытие текстового файла для чтения, записи или добавления Методы FileSystemObject.CreateTextFile или File.OpenAsTextStream
Чтение информации из заданного текстового файла или запись ее в него Методы объекта TextStream

Перейдем теперь к подробному рассмотрению объектов, используемых при работе с файловой системой.

Объект FileSystemObject

Объект FileSystemObject является основным объектом, обеспечивающим доступ к файловой системе компьютера; его методы используются для создания остальных объектов (Drives, Drive, Folders, Folder, Files, File и TextStream).

Для создания внутри сценария экземпляра объекта FileSystemObject можно воспользоваться методом CreateObject объекта WScript:

var FSO = WScript.CreateObject("Scripting.FileSystemObject");

Также можно использовать объект ActiveXObject языка JScript (с помощью этого объекта можно работать с файловой системой из сценариев, находящихся внутри HTML-страниц):

var FSO = new ActiveXObject("Scripting.FileSystemObject");

Объект FileSystemObject имеет единственное свойство Drives, в котором хранится коллекция, содержащая объекты Drive для всех доступных дисков компьютера. Примеры, иллюстрирующие использование свойства Drives приведены ниже в разд. "Коллекция Drives".

Методы объекта FileSystemObject представлены в табл. 5.2.


Таблица 5.2. Методы объекта FileSystemObject

Метод Описание
BuildPath(path, name) Добавляет к заданному пути (параметр path) новое имя (параметр name)
CopyFile(source, destination [, overwrite]) Копирует один или несколько файлов из одного места (параметр source) в другое (параметр destination)
CopyFolder(source, destination [, overwrite]) Копирует каталог со всеми подкаталогами из одного места (параметр source) в другое (параметр destination)
CreateFolder(foldername) Создает новый каталог с именем foldername. Если каталог foldername уже существует, то произойдет ошибка
CreateTextFile(filename [/overwrite[, unicode]]) Создает новый текстовый файл с именем filename и возвращает указывающий на этот файл объект TextStream
DeleteFile(filespec [, force]) Удаляет файл, путь к которому задан параметром filespec
DeleteFolder(folderspec [, force]) Удаляет каталог, путь к которому задан параметром folderspec, вместе со всем его содержимым
DriveExists(drivespec) Возвращает True, если заданное параметром drivespec устройство существует и False в противном случае
FileExists(filespec) Возвращает True, если заданный параметром filespec файл существует и False в противном случае
FolderExists(folderspec) Возвращает True, если заданный параметром folderspec каталог существует и False в противном случае
GetAbsolutePathName(pathspec) Возвращает полный путь для заданного относительного пути pathspec (из текущего каталога)
GetBaseName(path) Возвращает базовое имя (без расширения) для последнего компонента в пути path
GetDrive(drivespec) Возвращает объект Drive, соответствующий диску, заданному параметром drivespec
GetDriveName(path) Возвращает строку, содержащую имя диска в заданном пути. Если из параметра path нельзя выделить имя диска, то метод возвращает пустую строку (" ")
GetExtensionName(path) Возвращает строку, содержащую расширение для последнего компонента в пути path. Если из параметра path нельзя выделить компоненты пути, то GetExtensionName возвращает пустую строку (""). Для сетевых дисков корневой каталог (\) рассматривается как компонент пути
GetFile(filespec) Возвращает объект File, соответствующий файлу, заданному параметром filespec. Если файл, путь к которому задан параметром filespec, не существует, то при выполнении метода GetFile возникнет ошибка
GetFileName(pathspec) Возвращает имя файла, заданного полным путем к нему. Если из параметра pathspec нельзя выделить имя файла, метод GetFileName возвращает пустую строку ("")
GetFolder(folderpec) Возвращает объект Folder, соответствующий каталогу, заданному параметром folderspec. Если каталог, путь к которому задан параметром folderspec, не существует, при выполнении метода GetFolder возникнет ошибка
GetParentFolderName(path) Возвращает строку, содержащую имя родительского каталога для последнего компонента в заданном пути. Если для последнего компонента в пути, заданном параметром path, нельзя определить родительский каталог, то метод возвращает пустую строку ("")
GetSpecialFolder(folderpec) Возвращает объект Folder для некоторых специальных папок Windows, заданных числовым параметром folderspec
GetTempName() Возвращает случайным образом сгенерированное имя файла или каталога, которое может быть использовано для операций, требующих наличия временного файла или каталога
MoveFile(source, destination) Перемещает один или несколько файлов из одного места (параметр source) в другое (параметр destination)
MoveFolder(source, destination) Перемещает один или несколько каталогов из одного места (параметр source) в другое (параметр destination)
OpenTextFile(filename[, iomode[, create[, format]]]) Открывает заданный текстовый файл и возвращает объект TextStream для работы с этим файлом

Сами названия методов объекта FileSystemObject довольно прозрачно указывают на выполняемые ими действия. Приведем необходимые пояснения и примеры для перечисленных методов.

Методы CopyFile и CopyFolder

Для копирования нескольких файлов или каталогов в последнем компоненте параметра source можно указывать групповые символы "?" и "*"; в параметре destination групповые символы недопустимы. Например, следующий пример является корректным кодом:

FSO = WScript.CreateObject("Scripting.FileSystemObject");
FSO.CopyFile("с:\\mydocuments\\letters\\*.doc", "с:\\tempfolder\\");

А так писать нельзя:

FSO = WScript.CreateObject("Scripting.FileSystemObject");
FSO.CopyFile("с:\\mydocuments\\*\\R1???97.xls", "с:\\tempfolder");

Необязательный параметр overwrite является логической переменной, определяющей, следует ли заменять уже существующий файл/каталог с именем destination (overwrite=true) или нет (overwrite=false).

При использовании методов CopyFile и CopyFolder процесс копирования прерывается после первой возникшей ошибки (как и в команде COPY операционной системы).

Метод CreateTextFile

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

Параметр unicode является логическим значением, указывающим, в каком формате (ASCII или Unicode) следует создавать файл. Если unicode равно true, то файл создается в формате Unicode, если же unicode равно false или этот параметр вообще не указан, то файл создается в режиме ASCII.

Для дальнейшей работы с созданным файлом, т.е. для записи или чтения информации, нужно использовать методы объекта TextStream. Соответствующий пример сценария приведен в листинге 5.1.

Листинг 5.1. Создание текстового файла и запись в него строки

Методы DeleteFile и DeleteFolder

Параметры filespec или folderspec, используемые в методах, могут содержать групповые символы "?" и "*" в последнем компоненте пути для удаления сразу нескольких файлов/каталогов.

Если параметр force равен false или не указан вовсе, то с помощью методов DeleteFile или DeleteFolder будет нельзя удалить файл/каталог с атрибутом "только для чтения" (read-only). Установка для force значения true позволит сразу удалять такие файлы/каталоги.

!

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

Если заданный для удаления файл/каталог не будет найден, то возникнет ошибка.

Метод DriveExists

Для дисководов со съемными носителями метод DriveExists вернет true даже в том случае, если носитель физически отсутствует. Для того чтобы определить готовность дисковода, нужно использовать свойство IsReady соответствующего объекта Drive.

В качестве примера использования метода DriveExists приведем функцию ReportDriveStatus, которая возвращает информацию о наличии диска, передаваемого в эту функцию в качестве параметра (листинг 5.2).

Листинг 5.2. Функция ReportDriveStatus

Функция ReportDriveStatus будет возвращать информацию о наличии диска, передаваемого в эту функцию в качестве параметра.

Метод GetAbsolutePathName

Для иллюстрации работы этого метода предположим, что текущим каталогом является C:\MyDocuments\Reports. В табл. 5.3 приведены значения, возвращаемые методом GetAbsolutePathName, при различных значениях параметра pathspec.


Таблица 5.3. Варианты работы метода GetAbsolutePathName

Параметр pathspec Возвращаемое значение
"С:" "С:\MyDocuments\Reports"
"С:.." "С:\MyDocuments"
"С:\\" "С:\"
"Region1" "С:\MyDocuments\Reports\Region1"
"С:\\..\\..\\MyDocuments" "С:\МуDocuments" 

Метод GetBaseName

Работу этого метода иллюстрирует сценарий BaseName.js, приведенный в листинге 5.3. В результате выполнения этого сценария на экран выводится диалоговое окно, в котором отражены полный путь к файлу и базовое имя, выделенное из этого пути (рис. 5.1).

Рис. 5.1. Полный путь к файлу и базовое имя для этого пути


Листинг 5.3. Выделение базового имени файла

Метод GetDrive

Параметр drivespec в данном методе может задаваться одной буквой (например, "С"), буквой с двоеточием ("С:"), буквой с двоеточием и символом разделителя пути ("С:\\"). Для сетевого диска drivespec можно указывать в формате UNC (например, "Server1\\Programs").

Если параметр drivespec указывает на несуществующий диск или задан в неверном формате, то при выполнении метода GetDrive возникнет ошибка.

Если вам требуется преобразовать строку, содержащую обычный путь к файлу или каталогу, в вид, пригодный для GetDrive, необходимо применять методы GetAbsolutePathName и GetDriveName:

DriveSpec = GetDriveName(GetAbsolutePathName(Path))

Метод GetParentFolderName

Для иллюстрации работы этого метода запустим сценарий ParentFolder.js (листинг 5.4). В результате будет выведено диалоговое окно с полным путем к файлу и путь к родительскому каталогу этого файла (рис. 5.2).

Рис. 5.2. Полный путь к файлу и родительский каталог этого файла


Листинг 5.4. Определение родительского каталога для файла

Метод GetSpecialFolder

Параметр folderspec в этом методе является числом и может принимать значения, описанные в табл. 5.4.


Таблица 5.4. Значения параметра folderspec

Константа Значение Описание
WindowsFolder 0 Каталог Windows (например, "С:\Windows")
SystemFolder 1 Системный каталог, содержащий файлы библиотек, шрифтов и драйверы устройств
TemporaryFolder 2 Каталог для временных файлов, путь к которому хранится в переменной среды TMP 

Метод GetTempName

Метод GetTempName только возвращает имя файла, но не создает его. Для создания файла можно воспользоваться методом CreateTextFile, подставив в качестве параметра этого метода сгенерированное случайное имя (листинг 5.5).

Листинг 5.5. Создание временного файла со случайным именем

Методы MoveFile и MoveFolder

Как и при использовании методов CopyFile и CopyFolder, для перемещения нескольких файлов или каталогов в последнем компоненте параметра source можно указывать групповые символы (? и *); в параметре destination групповые символы недопустимы.

При использовании методов MoveFile и MoveFolder процесс перемещения прерывается после первой возникшей ошибки (как и в команде move операционной системы). Перемещать файлы и каталоги с одного диска на другой нельзя.

Метод OpenTextFile

Числовой параметр iomode задает режим ввода/вывода для открываемого файла и может принимать следующие значения (табл. 5.5).


Таблица 5.5. Параметр iomode

Константа Значение Описание
ForReading 1 Файл открывается только для чтения, записывать информацию в него нельзя
ForWriting 2 Файл открывается для записи. Если файл с таким именем уже существовал, то при новой записи его содержимое теряется
ForAppending 8 Файл открывается для добавления. Если файл уже существовал, то информация будет дописываться в конец этого файла

Параметр create имеет значение в том случае, когда открываемый файл физически не существует. Если create равно true, то этот файл создастся, если же в качестве значения create указано false или параметр create опущен, то файл создаваться не будет.

Числовой параметр format определяет формат открываемого файла (табл. 5.6).


Таблица 5.6. Параметр format

Константа Значение Описание
TristateUseDefault -2 Файл открывается в формате, используемом системой по умолчанию
TristateTrue -1 Файл открывается в формате Unicode
TristateFalse 0 Файл открывается в формате ASCII

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

В следующем примере с помощью метода OpenTextFile текстовый файл открывается в режиме добавления информации (листинг 5.6).

Листинг 5.6. Добавление информации в текстовый файл
!

Мнемонические константы, используемые в качестве параметров iomode и create, можно не определять явным образом в сценарии, как это сделано в вышеприведенном примере, а брать из самого объекта FileSystemObject (точнее говоря, из библиотеки типов этого объекта). Для этого в сценариях нужно применять разметку XML (см. листинг 3.9).

Объект Drive

С помощью объекта Drive можно получить доступ к свойствам заданного локального или сетевого диска. Создается объект Drive с помощью метода GetDrive объекта FileSystemObject следующим образом:

var FSO, D;
FSO = WScript.CreateObject("Scripting.FileSystemObject");
D = FSO.GetDrive("C:");

Также объекты Drive могут быть получены как элементы коллекции Drives.

Свойства объекта Drive представлены в табл. 5.7; методов у этого объекта нет.


Таблица 5.7. Свойства объекта Drive 

Свойство Описание
AvailableSpace Содержит количество доступного для пользователя места (в байтах) на диске
DriveLetter Содержит букву, ассоциированную с локальным устройством или сетевым ресурсом. Это свойство доступно только для чтения
DriveType Содержит числовое значение, определяющее тип устройства: 0 — неизвестное устройство; 1 — устройство со сменным носителем; 2 — жесткий диск; 3 — сетевой диск; 4 — CD-ROM; 5 — RAM-диск
FileSystem Содержит тип файловой системы, использующейся на диске (FAT, NTFS или CDFS)
FreeSpace Содержит количество свободного места (в байтах) на локальном диске или сетевом ресурсе. Доступно только для чтения
IsReady Содержит true, если устройство готово, и false в противном случае. Для устройств со сменными носителями и приводов CD-ROM IsReady возвращает true только в том случае, когда в дисковод вставлен соответствующий носитель и устройство готово предоставить доступ к этому носителю
Path Содержит путь к диску (например, "С:", но не "С:\")
RootFolder Содержит объект Folder, соответствующий корневому каталогу на диске. Доступно только для чтения
SerialNumber Содержат десятичный серийный номер тома заданного диска
ShareName Содержит сетевое имя для диска. Если объект не является сетевым диском, то в свойстве ShareName содержится пустая строка ("")
TotalSize Содержит общий объем в байтах локального диска или сетевого ресурса
VolumeName Содержит метку тома для диска. Доступно для чтения и записи

В листинге 5.7 приведен сценарий DriveInfo.js, в котором объект Drive используется для доступа к некоторым свойствам диска С: (рис. 5.3).

Рис. 5.3. Свойства диска С:


Листинг 5.7. Получение свойств диска С

Коллекция Drives

Доступная только для чтения коллекция Drives содержит объекты Drive для всех доступных дисков компьютера, в том числе для сетевых дисков и дисководов со сменными носителями.

В свойстве Count коллекции Drives хранится число ее элементов, т.е. число доступных дисков.

С помощью метода Item(drivespec) можно получить доступ к объекту Drive для диска, заданного параметром drivespec. Например:

var FSO, DriveCol, D; //Создаем объект FileSystemObject
FSO = WScript.CreateObject("Scripting.FileSystemObject");
//Создаем коллекцию имеющихся в системе дисков
DriveCol = FSO.Drives;
// Извлечение элемента коллекции (диск С:)
D = DriveCol.Item("С:");
//Вывод на экран метки тома диска С:
WScript.Echo("Диск С: имеет метку", D.VolumeName);

Для перебора всех элементов коллекции Drives нужно, как обычно, использовать объект Enumerator

В листинге 5.8 приведен файл ListDrives.js, в котором с помощью объекта Enumerator на экран выводятся сведения обо всех доступных дисках (рис. 5.4).

Рис. 5.4. Список всех дисков, имеющихся в системе


Листинг 5.8. Построение списка всех имеющихся дисков

Объект Folder

Объект Folder обеспечивает доступ к свойствам каталога. Создать этот объект можно с помощью свойства RootFolder объекта Drive или методов GetFolder, GetParentFolder и GetSpecialFolder объекта FileSystemObject следующим образом:

var FSO, Folder;
FSO = WScript.CreateObject("Scripting.FileSystemObject");
Folder = FSO.GetFolder("С:\\Мои документы");

Также объекты Folder могут быть получены как элементы коллекции Folders.

Свойства объекта Folder представлены в табл. 5.8.


Таблица 5.8. Свойства объекта Folder

Свойство Описание
Attributes Позволяет просмотреть или установить атрибуты каталога
DateCreated Содержит дату и время создания каталога. Доступно только для чтения
DateLastAccessed Содержит дату и время последнего доступа к каталогу. Доступно только для чтения
DateLastModified Содержит дату и время последней модификации каталога. Доступно только для чтения
Drive Содержит букву диска для устройства, на котором находится каталог. Доступно только для чтения
Files Содержит коллекцию Files, состоящую из объектов File для всех файлов в каталоге (включая скрытые и системные)
IsRootFolder Содержит true, если каталог является корневым, и false в противном случае
Name Позволяет просмотреть и изменить имя каталога. Доступно для чтения и записи
ParentFolder Содержит объект Folder для родительского каталога. Доступно только для чтения
Path Содержит путь к каталогу
ShortName Содержит короткое имя каталога (в формате 8.3)
ShortPath Содержит путь к каталогу, состоящий из коротких имен каталогов (в формате 8.3)
Size Содержит размер всех файлов и подкаталогов, входящих в данный каталог, в байтах
SubFolders Содержит коллекцию Folders, состоящую из всех подкаталогов каталога (включая подкаталоги с атрибутами "Скрытый" и "Системный")
Type Содержит информацию о типе каталога

Следующий пример показывает, как объект Folder используется для получения даты создания каталога (листинг 5.9).

Листинг 5.9. Вывод даты создания текущего каталога

Методы объекта Folder описаны в табл. 5.9.


Таблица 5.9. Методы объекта Folder

Метод Описание
Copy(destination [, overwrite]) Копирует каталог в другое место
CreateTextFile(filename[, overwrite [, unicode]]) Создает новый текстовый файл с именем filename и возвращает указывающий на этот файл объект TextStream (этот метод аналогичен рассмотренному выше методу CreateTextFile объекта FileSystemObject)
Delete([force]) Удаляет каталог
Move(destination) Перемещает каталог в другое место

Приведем необходимые замечания для методов из табл. 5.9.

Метод Copy

Обязательный параметр destination определяет каталог, в который будет производиться копирование; групповые символы в имени каталога недопустимы.

Параметр overwrite является логической переменной, определяющей, следует ли заменять уже существующий каталог с именем destination (overwrite=true) или нет (overwrite=false).

!

Вместо метода Сору можно использовать метод CopyFolder объекта FileSystemObject.

Метод Delete

Если параметр force равен false или не указан, то с помощью метода Delete будет нельзя удалить каталог с атрибутом "только для чтения" (read-only). Установка для force значения true позволит сразу удалять такие каталоги.

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

!

Вместо метода Delete можно использовать метод DeleteFolder объекта FileSystemObject.

Метод Move

Обязательный параметр destination определяет каталог, в который будет производиться перемещение; групповые символы в имени каталога недопустимы.

!

Вместо метода Move можно использовать метод MoveFolder объекта FileSystemObject

Коллекция Folders

Коллекция Folders содержит объекты Folder для всех подкаталогов определенного каталога. Создается эта коллекция с помощью свойства SubFolders соответствующего объекта Folder. Например, в следующем примере переменная SubFolders является коллекцией, содержащей объекты Folder для всех подкаталогов каталога C:\Program Files:

var FSO, F, SubFolders;
//Создаем объект FileSystemObject
FSO=WScript.CreateObject("Scripting.FileSystemObject");
//Создаем объект Folder для каталога C:\Program Files
F=FSO.GetFolder("C:\\Program Files");
//Создаем коллекцию подкаталогов каталога C:\Program Files
SubFolders=F.SubFolders;

Коллекция Folders (как и Drives) имеет свойство Count и метод Item. Кроме этого, у Folders есть метод Add(folderName), позволяющий создавать новые подкаталоги. В листинге 5.10 приведен сценарий MakeSubFold.js, который создает в каталоге "С:\Мои документы" подкаталог "Новая папка".

Листинг 5.10. Создание нового каталога
!

Напомним, что новый каталог также можно создать с помощью метода CreateFolder объекта FileSystemObject.

Для доступа ко всем элементам коллекции нужно использовать, как обычно, объект Enumerator. Например, в листинге 5.11 приведен сценарий ListSubFold.js, в котором на экран выводятся названия всех подкаталогов каталога C:\Program Files (рис. 5.5).

Рис. 5.5. Список всех подкаталогов каталога C:\Program Files


Листинг 5.11. Построение списка подкаталогов

Объект File

Объект File обеспечивает доступ ко всем свойствам файла. Создать этот объект можно с помощью метода GetFile объекта FileSystemObject следующим образом:

var FSO, F;
//Создаем объект FileSystemObject
FSO=WScript.CreateObject("Scripting.FileSystemObject");
//Создаем объект File
F=FSO.GetFile("С:\\Мои документах\letter.txt");

Также объекты File могут быть получены как элементы коллекции Files. Свойства объекта File описаны в табл. 5.10.


Таблица 5.10. Свойства объекта File

Свойство Описание
Attributes Позволяет просмотреть или установить атрибуты файлов
DateCreated Содержит дату и время создания файла. Доступно только для чтения
DateLastAccessed Содержит дату и время последнего доступа к файлу. Доступно только для чтения
DateLastModified Содержит дату и время последней модификации файла. Доступно только для чтения
Drive Содержит букву диска для устройства, на котором находится файл. Доступно только для чтения
Name Позволяет просмотреть и изменить имя файла. Доступно для чтения и записи
ParentFolder Содержит объект Folder для родительского каталога файла. Доступно только для чтения
Path Содержит путь к файлу
ShortName Содержит короткое имя файла (в формате 8.3)
ShortPath Содержит путь к файлу, состоящий из коротких имен каталогов (в формате 8.3)
Size Содержит размер заданного файла в байтах
Type Возвращает информацию о типе файла. Например, для файла с расширением txt возвратится строка "Text Document"

Методы объекта File представлены в табл. 5.11.


Таблица 5.11. Методы объекта File

Метод Описание
Copy(destination [, overwrite]) Копирует файл в другое место
Delete([force]) Удаляет файл
Move(destination) Перемещает файл в другое место
OpenAsTextStream([iomode, [format]]) Открывает заданный файл и возвращает объект TextStream, который может быть использован для чтения, записи или добавления данных в текстовый файл

Приведем необходимые замечания для методов из табл. 5.11. 

Метод Copy

Обязательный параметр destination определяет файл, в который будет производиться копирование; групповые символы в имени файла недопустимы.

Параметр overwrite является логической переменной, определяющей, следует ли заменять уже существующий файл с именем destination (overwrite=true) или нет (overwrite=false).

В листинге 5.12 приведен сценарий CopyFile.js, иллюстрирующий использование метода Сору. В этом сценарии на диске С: создается файл TestFile.txt, который затем копируется на рабочий стол.

Листинг 5.12. Создание текстового файла и копирование его в другой каталог
!

Вместо метода Сору можно использовать метод CopyFile объекта FileSystemObject.

Метод Delete

Если параметр force равен false или не указан, то с помощью метода Delete будет нельзя удалить файл с атрибутом "только для чтения" (read-only). Установка для force значения true позволит сразу удалять такие файлы.

!

Вместо метода Delete можно использовать метод DeleteFile объекта FileSystemObject.

Метод Move

Обязательный параметр destination определяет файл, в который будет производиться перемещение; групповые символы в имени файла недопустимы.

!

Вместо метода Move можно использовать метод MoveFile объекта FileSystemObject.

Метод OpenAsTextStream

Числовой параметр iomode задает режим ввода/вывода для открываемого файла и может принимать те же значения, что и одноименный параметр в методе OpenTextFile объекта FileSystemObject (табл. 5.5).

Числовой параметр format определяет формат открываемого файла (ASCII или Unicode). Этот параметр также может принимать те же значения, что и format в методе OpenTextFile объекта FileSystemObject (табл. 5.6).

!

Открыть текстовый файл для чтения можно также с помощью метода OpenTextFile объекта FileSystemObject.

В листинге 5.13 приведен сценарий WriteTextFile.js, иллюстрирующий использование метода OpenAsTextStream для записи строки в файл и чтения из него.

Листинг 5.13. Запись информации в текстовый файл и чтение ее из него

Коллекция Files

Коллекция Files содержит объекты File для всех файлов, находящихся внутри определенного каталога. Создается эта коллекция с помощью свойства Files соответствующего объекта Folder. Например, в следующем примере переменная Files является коллекцией, содержащей объекты File для всех файлов в каталоге С:\Мои документы:

var FSO, F, Files;
FSO=WScript.CreateObject("Scripting.FileSystemObject");
F=FSO.GetFolder("С:\\Мои документы");
Files=F.Files;

Как и рассмотренные выше коллекции Drives и Folders, коллекция Files имеет свойство Count и метод Item.

Для доступа в цикле ко всем элементам коллекции Files применяется объект Enumerator. В качестве примера использования этого объекта в листинге 5.14 приведен сценарий ListFiles.js, выводящий на экран названия всех файлов, которые содержатся в специальной папке "Мои документы" (рис. 5.6). 

Рис. 5.6. Список всех файлов в специальной папке "Мои документы"


Листинг 5.14. Построение списка файлов

Объект TextStream

Объект TextStream обеспечивает последовательный (строка за строкой) доступ к текстовому файлу. Методы этого объекта позволяют читать информацию из файла и записывать ее в него.

Создать объект TextStream можно с помощью следующих методов:

CreateTextFile объектов FileSystemObject и Folder;

OpenTextFile объекта FileSystemObject;

OpenAsTextStream объекта File.

В следующем примере переменная F является объектом TextStream и используется для записи строки текста в файл C:\TestFile.txt:

//Создаем объект FileSystemObject
var FSOWScript.CreateObject("Scripting. FileSystemObject");
//Создаем текстовый файл
var F=FSO.CreateTextFile("C:\\TestFile.txt", true);
//Записываем строку в файл
F.WriteLine("Строка текста");
//Закрываем файл
F.Close();

Свойству объекта TextStream описаны в табл. 5.12.


Таблица 5.12. Свойства объекта TextStream

Свойство Описание
AtEndOfLine Содержит true, если указатель достиг конца строки в файле, и false в противном случае. Доступно только для чтения
AtEndOfStream Содержит true, если указатель достиг конца файла, и false в противном случае. Доступно только для чтения
Column Содержит номер колонки текущего символа в текстовом файле. Доступно только для чтения
Line Содержит номер текущей строки в текстовом файле. Доступно только для чтения

Методы объекта TextStream представлены в табл. 5.13.


Таблица 5.13. Методы объекта TextStream

Метод Описание
Close() Закрывает открытый файл
Read(n) Считывает из файла n символов и возвращает полученную строку
ReadAll() Считывает полностью весь файл и возвращает полученную строку
ReadLine() Возвращает полностью считанную из файла строку
Skip(n) Пропускает при чтении n символов
SkipLine() Пропускает целую строку при чтении
Write(string) Записывает в файл строку string (без символа конца строки)
WriteBlankLines(n) Записывает в файл n пустых строк (символы перевода строки и возврата каретки)
WriteLine([string]) Записывает в файл строку string (вместе с символом конца строки). Если параметр string опущен, то в файл записывается пустая строка

В листинге 5.15 приведен сценарий TextFile.js, иллюстрирующий использование методов объекта TextStream. В этом сценарии на диске С: создается файл TestFile.txt и в него записываются три строки, вторая из которых является пустой. После этого файл открывается для чтения и из него считывается третья строка, которая выводится на экран (рис. 5.7).

Рис. 5.7. Результат работы сценария TextFile.js


Листинг 5.15. Работа с текстовым файлом с помощью методов объекта TextStream

Примеры сценариев 

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

Отчет об использовании дискового пространства

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

Диск: буква_диска 
Метка тома: метка  Общий объем, Mb: n1 
Используется, Mb: n2  Свободно, Mb: n3 

Для этого в сценарии вывод информации производится в текстовый файл rep.txt (переменная RepFile), который затем открывается с помощью Блокнота (рис. 5.8):

//Создаем объект WshShell
WshShell=WScript.CreateObject("WScript.Shell");
//Запускаем Блокнот (notepad.exe) и открываем в нем файл rep.txt
WshShell.Run("notepad.exe rep.txt"); 

Данные об одном диске формируются в функции WriteDriveInfo(drive), где в качестве параметра drive подставляется объект Drive для нужного диска. Соответствующие объекты Drive для всех дисков, имеющихся в системе, создаются в функции LoopDrives():

// Функция для перебора в цикле всех устройств (дисков)
function LoopDrives() {
 var Drives;
 //Создаем коллекцию дисков
 Drives = new Enumerator( FSO.Drives );
 //Цикл по всем дискам
 for(; !Drives.atEnd(); Drives.moveNext()) WriteDriveInfo(Drives.item());
}

Рис. 5.8. Сформированный отчет об использовании дискового пространства


В функции WriteDriveInfo(drive) сначала проверяется готовность устройства drive — если свойство IsReady объекта Drive равно true, то для этого устройства определяются общий объем (свойство TotalSize), объем свободного пространства (свойство FreeSpace), буква диска (свойство DriveLetter) и метка тома (свойство FreeSpace):

//Вычисляем общий объем диска в мегабайтах
Total = Math.round(drive.TotalSize/1048576);
//Вычисляем объем свободного пространства в мегабайтах
Free = Math.round(drive.FreeSpace/1048576);
//Вычисляем объем использованного пространства в мегабайтах
Used = Total - Free;
//Определяем букву диска
DriveLetter=drive.DriveLetter+":";
//Определяем метку тома
VolumeName=drive.VolumeName;

Строки с полученными значениями затем приводятся к нужному виду с помощью вспомогательных функций LFillStr (выравнивание строки влево), FillStr (выравнивание строки по центру) и записываются в выходной файл RepFile:

RepFile.WriteLine("+---------------------------------------------------+");
//Записываем информацию о букве диска
s="|"+FillStr(51,"Диск "+DriveLetter)+"|";
RepFile.WriteLine(s);
RepFile.WriteLine("+---------------------------------------------------+");
//Записываем информацию о метке тома
s="|"+LFillStr(25,"Метка тома: "+VolumeName)+"|";
//Записываем информацию об общем объеме диска
s+=LFillStr(25,"Общий объем, Mb: "+Total)+"|";
RepFile.WriteLine(s);
RepFile.WriteLine("+---------------------------------------------------+");
//Записываем информацию об использованном пространстве
s="|"+LFillStr(25,"Используется, Mb: "+Used.toString())+"|";
//Записываем информацию о свободном пространстве
s+=LFillStr(25,"Свободно, Mb: "+Free.toString())+"|";
RepFile.WriteLine(s);
RepFile.WriteLine("+---------------------------------------------------+");

Если же устройство drive не готово (свойство IsReady равно false), то с помощью свойства DriveType проверяется, не является ли ли диск сетевым (в этом случае DriveType=3), после чего в файл выводится соответствующее сообщение:

if (drive.DriveType == 3) { //Проверяем, является ли диск сетевым
 //Записываем информацию о букве диска
 RepFile.WriteLine( "Диск " + drive.DriveLetter + " является сетевым" );
 //Записываем пустые строки
 RepFile.WriteLine();
 RepFile.WriteLine();
} else {
 //Устройство не готово
 RepFile.WriteLine( "Устройство " + drive.DriveLetter + ": не готово" );
 //Записываем пустые строки
 RepFile.WriteLine();
 RepFile.WriteLine();
}

Полный текст сценария DrivesReport.js приведен в листинге 5.16.

Листинг 5.16. Отчет об использовании дискового пространства для всех устройств на компьютере

Удаление ненужных временных файлов с жесткого диска

В результате некорректного завершения приложений на жестком диске часто остаются "бесхозные" временные файлы (с расширением tmp), которые затем приходится удалять вручную. Весьма удобно было бы удалять все такие файлы сразу со всего жесткого диска, не заботясь о том, в каких каталогах они находятся. Используя стандартные средства операционной системы, можно сначала с помощью пункта Найти (Find) меню Пуск (Start) составить список всех временных файлов (рис. 5.9), затем выделить все файлы в этом списке и нажать комбинацию клавиш <Shift>+<Delete> (удаление файлов без помещения в Корзину).

Однако если хотя бы один из временных файлов будет занят каким-либо приложением, то в доступе к нему будет отказано и процесс удаления прервется (рис. 5.10).

Поэтому для удаления с жесткого диска всех временных файлов мы напишем сценарий DelTmp.js (основная идея, которая используется в данном сценарии, позаимствована из статьи [6]).

Алгоритм работы сценария состоит в следующем:

• в Блокноте (notepad.exe) создается новый файл для отображения в нем результатов работы;

• на диске D: просматриваются подкаталоги всех уровней вложенности;

• в каждом подкаталоге ищутся все временные файлы с расширением tmp;

• для каждого найденного временного файла производится попытка удаления. В случае успеха в Блокноте печатается путь к файлу и слово "OK", если же удаляемый файл занят, то печатается путь к файлу и слово "Busy" ("Занят");

• после просмотра всех каталогов в Блокноте печатается общее количество найденных временных файлов (рис. 5.11).

Рис. 5.9. Список всех временных файлов на диске D:


Рис. 5.10. Ошибка, возникающая при попытке удалить занятый файл 


Итак, наиболее важными в сценарии являются: функция DelFilesInFolder(Fold, SExt), в которой происходит попытка удаления в каталоге Fold всех файлов, имеющих расширение SExt, и рекурсивная (т.е. содержащая обращение к самой себе) функция LoopSubFolders(Fold), в которой происходит вызов функции DelFilesInFolder для подкаталогов каталога Fold.

Рис. 5.11. Результат работы сценария DelTmp.js


Рассмотрим сначала функцию DelFilesInFolder(Fold, SExt). Здесь сначала создается объект Enumerator с именем Files для доступа к коллекции всех файлов в каталоге Fold:

var Files, s, SPath, FileExt, Status;
Files=new Enumerator(Fold.Files);

после чего все элементы коллекции просматриваются в цикле while:

s="";
//Цикл по всем файлам
while (!Files.atEnd()) {
 …
 Files.moveNext(); //Переходим к следующему файлу
}

Для текущего файла в коллекции выделяется его расширение, которое преобразуется к верхнему регистру:

//Определяем путь к файлу
SPath=Files.item().Path;
//Выделяем расширение файла
FileExt=FSO.GetExtensionName(SPath).toUpperCase();

В случае совпадения расширения FileExt с расширением SExt в блоке try…catch производится попытка удаления текущего файла:

ColTmp++; //Увеличиваем счетчик файлов для удаления
try {
 Status="Ok";
 //Пытаемся удалить файл
 Files.item().Delete();
} catch (e) {
 //Обрабатываем возможные ошибки
 if (е != 0) {
  //Произошла ошибка при удалении файла
  Status="Busy";
 }
}

Таким образом, в переменной Status будет записан результат удаления файла: "OK" в случае успеха, и "Busy" в том случае, если удаляемый файл занят другим приложением. После этого полный путь к удаляемому файлу и значение переменной Status печатаются в окне Блокнота с помощью метода SendKeys объекта WshShell. Здесь только нужно учесть, что в имени файла могут встретиться символы, имеющие специальный смысл для метода SendKeys, поэтому предварительно нужно соответствующим образом заменить такие символы в имени файла:

//Заменяем специальные символы в названии файла
SPath=SPath.replace("~", "{-}");
SPath=SPath.replace("+", "{+}");
SPath=SPath.replace("^", "{^}");
SPath=SPath.replace("%", "{%}");
//Посылаем название файла и результат его удаления в Блокнот
WshShell.SendKeys(SPath+"{TAB}"+Status+"~");
//Приостанавливаем сценарий на 0,5 сек
WScript.Sleep(500);

Перейдем теперь к описанию функции LoopSubFolders(Fold). Сначала в этой функции удаляются временные файлы в каталоге Fold:

//Удаляем временные файлы из каталога Fold
DelFilesInFolder(Fold, ExtForDel);

Затем происходит удаление файлов во всех подкаталогах каталога Fold, причем делается это с помощью обращения для каждого подкаталога к той же функции LoopSubFolders:

//Создаем коллекцию подкаталогов
SubFolders = new Enumerator(Fold.SubFolders);
//Цикл по всем подкаталогам
while (!SubFolders.atEnd()) {
 //Вызываем рекурсивно функцию LoopSubFolders
 LoopSubFolders(SubFolders.item());
 //Переходим к следующему подкаталогу
 SubFolders.moveNext();
}

Полный текст сценария DelTmp.js приведен в листинге 5.17.

Листинг 5.17. Удаление всех временных файлов на диске D:

Поиск файлов с использованием регyлярных выражений

Всем хорошо известно, что для поиска файлов и папок с помощью стандартных средств Windows в именах можно использовать подстановочные символы "?" (обозначает любой один символ) и "*" (обозначает любое число любых символов). Например, на рис. 5.12 представлен результат поиска файлов *.sys (все файлы с расширением sys) на диске С:.

Рис. 5.12. Использование подстановочных символов при поиске файлов


В сценариях WSH можно производить поиск файлов (как и любого другого текста) с помощью гораздо более сложных правил для определения соответствий. Для этого используются регулярные выражения, которые определяют образец текста для поиска. Для задания этого образца используются литералы и метасимволы. Каждый символ, который не имеет специального значения в регулярных выражениях, рассматривается как литерал и должен точно совпасть при поиске. Метасимволы — это символы со специальным значением в регулярных выражениях. Описание наиболее часто используемых метасимволов приведено в табл. 5.14.


Таблица 5.14. Некоторые метасимволы, использующиеся в регулярных выражениях

Символы Описание
\ Следующий символ будет являться специальным символом или, наоборот, литералом. Например, n означает символ "n", а "\n" означает символ новой строки. Последовательности \\ соответствует символ "\", а \( — символ "("
^ Начало строки
$ Конец строки
* Предыдущий символ повторяется любое число раз (в том числе ни разу). Например, выражению zo* соответствуют как "z", так и "zoo"
+ Предыдущий символ повторяется не менее одного раза. Например, выражению zo+ соответствует "zoo", но не "z"
? Предыдущий символ повторяется не более одного раза
. (точка) Любой символ, кроме перевода строки
х|у Либо символ "х", либо символ "у". Например, выражению z|food соответствуют "z" или "food"
[xyz] Множество символов. Означает любой один символ из набора символов, заключенных в квадратные скобки. Например, выражению [abc] соответствует символ "а" в слове "plain"
[a-z] Диапазон символов. Означает любой один символ из заданного диапазона. Например, выражению [a-z] соответствует любая буква английского алфавита в нижнем регистре
[^m-z] Означает любой символ, не входящий в заданный диапазон. Например, выражению [^m-z] соответствует любой символ, не попадающий в диапазон символов от "m" до "z"
\b Граница слова, т.е. позиция между словом и пробелом. Например, выражению er\b соответствует символ "er" в слове "never", но не в слове "verb"
Позиция внутри слова (не на границе). Например, выражению еа*r\B соответствует подстрока "ear" в "never early"
\d Символ, обозначающий цифру. Эквивалентно [0-9]
\D Любой символ, кроме цифры. Эквивалентно [^0-9]

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

!

Более подробную информацию о регулярных выражениях можно найти, например, в документации Microsoft по языку VBScript.

В качестве примера использования регулярных выражений в листинге 5.18 приведен сценарий FindRegExp.js, в котором производится поиск в подкаталоге ForFind текущего каталога всех файлов, имена которых начинаются с символов "П", "А" или "И" и имеют расширение txt.

Для получения доступа к каталогу ForFind в сценарии используется метод GetFolder объекта FileSystemObject:

//Создаем объект WshShell
WshShell=WScript.CreateObject("WScript.Shell");
//Создаем объект FileSystemObject
FSO=WScript.CreateObject("Scripting.FileSystemObject");
//Создаем объект Folder для доступа к подкаталогу ForFind
//текущего каталога
Folder = FSO.GetFolder(WshShell.CurrentDirectory+"\\ForFind");

Поиск нужных файлов будет выполняться с помощью следующего регулярного выражения:

//Создаем регулярное выражение (объект RegExp)
RegEx=new RegExp("^[ПАИ].*\.txt$", "i");

Сам поиск и вывод имен найденный файлов производятся в функции FindFilesInFolder(Fold, RegEx). Здесь сначала инициализируются счетчик найденных файлов и переменная, в которой будут сохраняться имена найденных файлов, а также создается объект Enumerator (переменная Files) для доступа к файлам каталога Fold:

ColFind=0; //Счетчик найденных файлов
SFileNames=""; //Строка с именами файлов
//Создаем коллекцию файлов в каталоге Fold
Files=new Enumerator(Fold.Files);

Элементы коллекции просматриваются в цикле while:

//Цикл по всем файлам в коллекции
while (!Files.atEnd()) {
 Files.moveNext(); //Переходим к следующему файлу
}

Для текущего файла в коллекции выделяется его имя, которое затем с помощью метода test объекта RegExp проверяется на соответствие заданному регулярному выражению:

//Выделяем имя файла
SName=Files.item().Name;
//Проверяем, соответствует ли имя файла регулярному выражению
if (RegEx.test(SName)) {
 ColFind++; //Увеличиваем счетчик найденных файлов
 //Добавляем имя файла к переменной SFileNames
 SFileNames+=SName+ " \n";
}

В конце функции FindFilesInFolder(Fold, RegEx) на экран выводятся имена найденных файлов и их общее количество:

SItog="Найдено файлов: "+ColFind;
//Выводим на экран имена и количество найденных файлов
WScript.Echo(SFileNames+SItog);
Листинг 5.18. Поиск файлов, имена которых соответствуют регулярному выражению

Перемещение файлов с ведением журнала действий

Поставим перед собой следующую задачу. Пусть в заданный каталог на жестком диске (например, C:\In) поступают из почтовой программы или по локальной сети файлы с различными расширениями. Требуется выделить из них все файлы с заданным расширением (например, 003) и перенести их в другой каталог (например, C:\Out). При этом необходимо вести журнал операций (log-файл), в который для каждого переносимого файла записывать следующую информацию: имя файла, дату и время его создания, дату и время перемещения файла. Структура log-файла (в нашем случае это файл C:\In\log.txt) должна быть следующей:

Имя файла (Дата и время создания) Дата и время перемещения

Например:

34556.003    (19/10/2002 10:45) 19/10/2002 11:02
43432_KL.003 (19/10/2002 10:45) 19/10/2002 11:02
45.003       (19/10/2002 10:45) 19/10/2002 11:02
              ...

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

Рис. 5.13. Информация о перемещении файлов


Поставленную задачу выполняет рассматриваемый ниже сценарий MoveLog.js; запускать этот сценарий следует в консольном режиме с помощью cscript.exe.

Пути к каталогу-источнику, в котором первоначально находятся файлы, и к целевому каталогу, в который будут перемещены эти файлы, хранятся соответственно в переменных Source и Dest:

var
 Source="C:\\In\\", //Путь к каталогу-источнику файлов для перемещения
 Dest="C:\\Out\\"; //Путь к целевому каталогу

В переменных Mask и PathLog записаны соответственно расширение файлов для перемещения и путь к log-файлу:

var
 Mask="003", //Расширение файлов для перемещения
 PathLog="C:\\In\\log.txt"; //Путь к log-файлу

Сначала в сценарии с помощью метода FolderExists объекта FileSystemObject проверяется наличие на диске каталога-источника; в случае отсутствия этого каталога выводится соответствующее сообщение и выполнение сценария прерывается:

//Создаем объект FileSystemObject
FSO=WScript.CreateObject("Scripting.FileSystemObject");
//Проверяем наличие каталога-источника
if (!FSO.FolderExists(Source)) {
 //Выводим сообщение об отсутствии каталога-источника
 WScript.Echo("Каталог-источник", Source, "не существует.");
 WScript.Echo("Нажмите Enter...");
 WScript.StdIn.ReadLine();
 //Выходим из сценария
 WScript.Quit();
}

Аналогичным образом проверяется наличие целевого каталога:

//Проверяем наличие целевого каталога
if (!FSO.FolderExists(Dest)) {
 //Выводим сообщение об отсутствии целевого каталога
 WScript.Echo("Целевой каталог", Dest, "не существует.");
 WScript.StdIn.ReadLine();
 WScript.StdIn.ReadLine();
 //Выходим из сценария
 WScript.Quit();
}

После этого создается объект Enumerator (переменная Files) для доступа к коллекции всех файлов в каталоге-источнике:

//Создаем объект Folder для каталога-источника Fold=FSO.GetFolder(Source);
//Создаем объект Enumerator для доступа к коллекции файлов
//в каталоге-источнике
Files=new Enumerator(Fold.Files);

Операции записи информации в log-файл и непосредственно переноса файлов из одного каталога в другой реализованы соответственно в функциях WriteLog() и MoveFiles().

В функции WriteLog() после объявления переменных открывается log-файл в режиме добавления строк:

var s, ss, s1, d, File, FLog;
WScript.Echo(" ");
WScript.Echo("Записываем информацию в log-файл...");
//Открываем log-файл для добавления
FLog=FSO.OpenTextFile(PathLog, ForAppending, true);

Затем в цикле while происходит просмотр коллекции файлов в каталоге-источнике:

//Переходим к первому элементу коллекции файлов
Files.moveFirst();
//Цикл по всем файлам в коллекции
while (!Files.atEnd()) {
 //Извлекаем текущий файл из коллекции
 File=Files.item();
 //Переходим к следующему файлу в коллекции
 Files.moveNext();
}

Если файл подлежит перемещению (расширение этого файла совпадает с расширением файлов для перемещения), то определяется его имя (свойство Name), дата создания (свойство DateCreated) и текущая дата (объект Date), и в log-файл записывается соответствующая информация:

//Выделяем расширение файла
s=FSO.GetExtensionName(File.Name);
//Проверяем, совпадает ли расширение текущего файла
//с расширением файлов для перемещения
if (s==Mask) {
 //Выводим имя файла на экран
 WScript.Echo("  "+File.Name);
 //Определяем дату создания файла
 d=new Date(File.DateCreated);
 //Формируем строку ss для записи в log-файл
 ss=LFillStr(13,File.Name)
 s1="("+DateToStr(d)+" ";
 s1+=TimeToStr(d)+")";
 ss+=LFillStr(20,s1);
 //Определяем текущую дату
 d=new Date();
 ss+=DateToStr(d);
 ss+=" "+TimeToStr(d);
 //Записываем сформированную строку в log-файл
 FLog.WriteLine(ss);
}

Записываемая в log-файл строка формируется в нужном виде с помощью вспомогательных функций LFillStr (выравнивание строки влево в поле заданной длины), DateToStr (формирование из объекта Date строки формата ДД/ММ/ГГГГ) и TimeTostr (формирование из объекта Date строки формата ЧЧ:ММ).

В функции MoveFiles(), как и в WriteLog(), производится перебор в цикле while файлов каталога-источника (элементов коллекции Files). Перемещение файлов осуществляется с помощью последовательного применения методов Copy и Delete:

Files.moveFirst();
//Цикл по всем файлам в коллекции
while (!Files.atEnd()) {
 //Извлекаем текущий файл из коллекции
 File=Files.item();
 //Выделяем расширение файла
 s=FSO.GetExtensionName(File.Name);
 //Проверяем, совпадает ли расширение текущего файла
 //с расширением файлов для перемещения
 if (s==Mask) {
  //Выводим имя файла на экран
  WScript.Echo("  "+File.name);
  //Копируем файл в целевой каталог
  File.Copy(Dest);
  //Удаляем файл
  File.Delete();
  //Увеличиваем счетчик количества перемещенных файлов
  Col++;
 }
 //Переходим к следующему файлу в коллекции
 Files.moveNext();
}

После перемещения всех файлов на экран выводится информация об их количестве:

WScript.Echo("Перемещено файлов:", Col);
WScript.Echo("Нажмите Enter...");
WScript.StdIn.ReadLine();

Полный текст сценария MoveLog.js приведен в листинге 5.19.

Листинг 5.19. Поиск файлов с ведением log-файла

Разработка записной книжки в формате текстового файла

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

Предположим, что имеется файл book.txt, содержащий информацию из записной книжки в следующем формате:

Фамилия|Имя|Телефон|Улица|Дом|Кв.|Примечание

В качестве примера мы будем рассматривать файл book.txt, приведенный в листинге 5.20.

Листинг 5.20. Содержимое файла book.txt

Ниже приведен сценарий SortName.js, который реализует одну из функций для работы с записной книжкой — в результате работы этого сценария все записи из book.txt сортируются по фамилии и отображаются в Блокноте (рис. 5.14).

Опишем кратко алгоритм работы сценария SortName.js.

1. Информация из файла book.txt считывается в массив PersonArr. Каждый элемент массива является объектом типа Person, в котором хранятся все данные для одного человека.

2. Массив PersonArr сортируется в нужном порядке (в нашем случае — по возрастанию фамилий).

3. Содержимое всех записей из массива PersonArr выводится в текстовый файл out.txt.

4. Файл out.txt открывается в Блокноте.

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

Рис. 5.14. Содержимое записной книжки (сортировка по фамилии)


Запускной функцией в SortName.js является функция Main():

function Main() {
 //Создаем объект WshShell
 WshShell = WScript.CreateObject("WScript.Shell");
 //Определяем пути к файлам
 InitPath();
 //Создаем объект FileSystemObject
 FSO=WScript.CreateObject("Scripting.FileSystemObject");
 //Открываем выходной файл для записи
 FOut=FSO.OpenTextFile(PathOut,ForWriting,true);
 //Печатаем заголовок отчета
 TopReport("Сортировка по фамилии");
 //Выводим содержимого файла с данными
 ListFile();
 //Печатаем итоговую информацию
 BottomReport();
 //Открываем выходной файл в Блокноте
 MakeOut();
}

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

function ListFile() {
 //Считывание данных из файла в массив
 FileToArray();
 //Запись информации из массива в выходной файл
 ListPersonArray();
}

Опишем сначала функцию FileToArray(). Здесь производится создание массива PersonArr, чтение в цикле while строк из файла book.txt (с помощью метода ReadLine) и формирование массива ss (с помощью метода split), элементы которого содержат данные для текущей записи. После этого вызывается функция PersonToArray() для создания нового элемента массива PersonArr:

function FileToArray() {
var s,ss;
 //Открываем файл с данными для чтения
 FBook=FSO.OpenTextFile(PathBook,ForReading,true);
 //Создаем массив PersonArr
 PersonArr=new Array(); 
 //Читаем содержимое файла FBook
 while (!FBook.AtEndOfStream) {
  //Считываем строку
  s=FBook.ReadLine();
  //Записываем содержимое строки s в массив ss
  ss = s.split("|");
  //Добавляем новый элемент в массив объектов Person
  PersonToArray(ss);
 }
 //Закрываем файл
 FBook.Close();
}

В функции PersonToArray(sArr) из элементов массива sArr формируется экземпляр PersonRec объекта Person. После этого объект PersonRec добавляется в массив PersonArr:

function PersonToArray(sArr) {
 //Создаем новый объект Person
 PersonRec=new Person(sArr[0], sArr[1], sArr[2], sArr[3], sArr[4], sArr[5], sArr[6]);
 //Сохраняем объект Person в массиве
 PersonArr[PersonArr.length]=PersonRec;
}

Конструктор объекта Person имеет следующий вид:

function Person(LastName,Name,Phone,Street,House,App,Note) {
 this.LastName=LastName; //Фамилия
 this.Name=Name;         //Имя
 this.Phone=Phone;       //Телефон
 this.Street=Street;     //Улица
 this.House=House;       //Дом
 this.App=App;           //Квартира
 this.Note=Note;         //Примечание
}

Перейдем теперь к рассмотрению функции ListPersonArray():

function ListPersonArray() {
var i;
 //Сортировка массива по фамилии
 PersonArr.sort(SortLastName);
 //Цикл по всем элементам массива PersonArr
 for (i=0;i<=PersonArr.length-1;i++) {
  //Запись информации в выходной файл
  PrintPerson(PersonArr[i]);
 }
}

Сначала здесь производится сортировка массива PersonArr в возрастающем порядке по фамилиям, для чего в качестве параметра метода sort указывается имя SortLastName функции, которая производит сравнение двух элементов массива:

function SortLastName(Pers1,Pers2) {
 if (Pers1.LastName<Pers2.LastName) return -1;
 else if (Pers1.LastName==Pers2.LastName) return 0;
 else return 1;
}
!

Сортировать массивы подобным образом можно только в сценариях JScript, где массивы рассматриваются как объекты. В сценариях VBScript отсутствуют встроенные средства для сортировки массивов

После сортировки массива содержимое его элементов в цикле выводится в файл out.txt с помощью функции PrintPerson(PersRec):

function PrintPerson(PersRec) {
 FOut.WriteLine("Фамилия : "+PersRec.LastName);
 FOut.WriteLine("Имя : "+PersRec.Name);
 FOut.WriteLine("Телефон: "+PersRec.Phone);
 FOut.WriteLine("Улица: "+PersRec.Street);
 FOut.WriteLine("Дом: "+PersRec.House);
 FOut.WriteLine("Кв.: "+PersRec.App);
 FOut.WriteLine("Заметки: "+PersRec.Note);
 FOut.WriteLine("*********************************");
 //Увеличиваем счетчик числа записей
 NomRec++;
}

В листинге 5.21 приводится полный текст сценария SortName.js.

Листинг 5.21. Вывод содержимого записной книжки с сортировкой по фамилии


 

Глава 5. Доступ из сценариев к файловой системе