Глава 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. Создание текстового файла и запись в него строки

/*******************************************************************/

/* Имя: CreateFile.js                        */

/* Язык: JScript                          */

/* Описание: Создание текстового файла и запись в него строки    */

/*******************************************************************/

var FSO,f; //Объявляем переменные

//Создаем объект FileSystemObject

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

//Создаем на диске C: текстовый файл TestFile.txt

f = FSO.CreateTextFile("C:\\TestFile.txt", true); 

//Записываем строку в файл

f.WriteLine("Привет!"); 

//Закрываем файл

f.Close();

/*************  Конец *********************************************/

Методы 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

function ReportDriveStatus(drv) {

 var FSO, s ="" //Объявляем переменные

 //Создаем объект FileSystemObject

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

 //Проверяем наличие диска drv

 if (FSO.DriveExists(drv)) s += "Диск " + drv + " существует.";

 else s += "Диск " + drv + " не существует.";

 return(s);

}

Функция

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. Выделение базового имени файла

/*******************************************************************/

/* Имя: BaseName.js                         */

/* Язык: JScript                          */

/* Описание: Создание текстового файла и запись в него строки    */

/*******************************************************************/

var FSO, BaseName, SPath,s;  //Объявляем переменные

//Создаем объект FileSystemObject

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

//Задаем путь к файлу

SPath="C:\\Мои документы\\letter.txt";

//Выделяем базовое имя файла (без расширения)

BaseName = FSO.GetBaseName(SPath);

//Выводим на экран путь и базовое имя

s="Путь: "+SPath+"\n";

s+="Базовое имя: "+BaseName;

WScript.Echo(s);

/*************  Конец *********************************************/

Метод 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. Определение родительского каталога для файла

/*******************************************************************/

/* Имя: ParentFolder.js                       */

/* Язык: JScript                          */

/* Описание: Определение родительского каталога для файла      */

/*******************************************************************/

var FSO,ParentFolder,Spath,s;  //Объявляем переменные

//Создаем объект FileSystemObject

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

//Задаем путь к файлу

SPath="C:\\Programs\\letter.txt";

//Определяем родительский каталог для файла letter.txt

ParentFolder = FSO.GetParentFolderName(SPath);

s="Путь: "+SPath+"\n";

s+="Родительский каталог: "+ParentFolder;

//Выводим на экран полный путь к файлу letter.txt

//и родительский каталог для этого файла

WScript.Echo(s);

/*************  Конец *********************************************/

Метод GetSpecialFolder

Параметр

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


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

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

Метод GetTempName

Метод

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

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

/*******************************************************************/

/* Имя: TempFile.js                         */

/* Язык: JScript                          */

/* Описание: Создание временного файла со случайным именем     */

/*******************************************************************/

var FSO,FileName,f,s;  //Объявляем переменные

//Создаем объект FileSystemObject

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

//Генерируем случайное имя файла

FileName=FSO.GetTempName();

//Создаем файл и именем FileName

f = FSO.CreateTextFile(FileName, true); 

//Закрываем файл

f.Close();

//Сообщаем о создании файла

WScript.Echo("Был создан файл",FileName);

/*************  Конец *********************************************/

Методы 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. Добавление информации в текстовый файл

/*******************************************************************/

/* Имя: AppendFile.js                        */

/* Язык: JScript                          */

/* Описание: Добавление строки в текстовый файл           */

/*******************************************************************/

//Объявляем переменные и инициализируем константы

var FSO,f,ForAppending = 8;

//Создаем объект FileSystemObject

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

//Открываем файл

f = FSO.OpenTextFile("C:\\TestFile.txt", ForAppending, true);

//Добавление в файл строку

f.WriteLine("Привет!");

//Закрываем файл

f.Close();

/*************  Конец *********************************************/

Замечание

Мнемонические константы, используемые в качестве параметров

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. Получение свойств диска С

/*******************************************************************/

/* Имя: DriveInfo.js                        */

/* Язык: JScript                          */

/* Описание: Вывод на экран свойств диска C:            */

/*******************************************************************/

//Объявляем переменные

var FSO,D,TotalSize,FreeSpace,s;

//Создаем объект FileSystemObject

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

//Создаем объект Drive для диска C:

D = FSO.GetDrive("C:");

s="Информация о диске C:\n";

//Получаем серийный номер диска

s+="Серийный номер: "+D.SerialNumber+"\n";

//Получаем метку тома диска

s+="Метка тома: "+D.VolumeName+"\n";

//Вычисляем общий объем диска в килобайтах

TotalSize=D.TotalSize/1024;

s+="Объем: "+TotalSize+" Kb\n";

//Вычисляем объем свободного пространства диска в килобайтах

FreeSpace=D.FreeSpace/1024;

s+="Свободно: "+FreeSpace+" Kb\n";

//Выводим свойства диска на экран

WScript.Echo(s);

/*************  Конец *********************************************/

Коллекция 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. Построение списка всех имеющихся дисков

/*******************************************************************/

/* Имя: ListDrives.js                        */

/* Язык: JScript                          */

/* Описание: Получение списка всех имеющихся дисков         */

/*******************************************************************/

//Объявляем переменные

var FSO,s,ss,Drives,D;

//Создаем объект FileSystemObject

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

//Создаем коллекцию дисков, имеющихся в системе

Drives = new Enumerator(FSO.Drives);

s="";

//Цикл по всем дискам в коллекции

for (;!Drives.atEnd();Drives.moveNext()) {

 //Извлекаем текущий элемента коллекции

 D=Drives.item();

 //Получаем букву диска

 s+=D.DriveLetter;

 s+=" - ";

 if (D.DriveType == 3) //Проверяем, не является ли диск сетевым

  //Получаем имя сетевого ресурса

  ss=D.ShareName;

 else 

  //Диск является локальным

  if (D.IsReady)  //Проверяем готовность диска

  //Если диск готов, то получаем метку тома для диска

  ss=D.VolumeName;

  else ss="Устройство не готово";

 s+=ss+"\n";

}

//Выводим полученные строки на экран

WScript.Echo(s);

/*************  Конец *********************************************/

Объект 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. Вывод даты создания текущего каталога

/*******************************************************************/

/* Имя: DateFolder.js                        */

/* Язык: JScript                          */

/* Описание: Вывод на экран даты создания текущего каталога     */

/*******************************************************************/

var FSO,WshShell,s;  //Объявляем переменные

//Создаем объект FileSystemObject

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

//Создаем объект WshShell

WshShell=WScript.CreateObject("WScript.Shell");

//Определяем каталог, из которого был запущен сценарий

//(текущий каталог)

Folder = FSO.GetFolder(WshShell.CurrentDirectory);

//Получаем имя текущего каталога

s="Текущий каталог: "+Folder.Name+"\n";

//Получаем дату создания текущего каталога

s+="Дата создания: "+Folder.DateCreated+"\n";

//Выводим информацию на экран

WScript.Echo(s);

/*************  Конец *********************************************/


Методы объекта

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. Создание нового каталога

/*******************************************************************/

/* Имя: MakeSubFold.js                       */

/* Язык: JScript                          */

/* Описание: Создание нового каталога                */

/*******************************************************************/

//Объявляем переменные

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;

// Создаем каталог C:\Program Files\Новая папка

SubFolders.Add("Новая папка");

/*************  Конец *********************************************/

Замечание

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

CreateFolder
объекта
FileSystemObject
.

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

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

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


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

/*******************************************************************/

/* Имя: ListSubFold.js                       */

/* Язык: JScript                          */

/* Описание: Получение списка всех подкаталогов заданного каталога */

/*******************************************************************/

//Объявляем переменные

var FSO,F,SFold,SubFolders,s;

//Создаем объект FileSystemObject

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

//Путь к каталогу

SFold="C:\\Program Files";

s="Каталог "+SFold+"\n";

s+="Подкаталоги:\n";

//Создаем объект Folder для каталога C:\Program Files

F=FSO.GetFolder(SFold);

//Создаем коллекцию подкаталогов каталога C:\Program Files

SubFolders= new Enumerator(F.SubFolders);

//Цикл по всем подкаталогам

for (; !SubFolders.atEnd(); SubFolders.moveNext()) {

 s+=SubFolders.item()+"\n";  //Добавляем строку с именем подкаталога

}

//Выводим полученные строки на экран

WScript.Echo(s);

/*************  Конец *********************************************/

Объект 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.js                         */

/* Язык: JScript                          */

/* Описание: Создание и копирование файла              */

/*******************************************************************/

//Объявляем переменные

var FSO,F,WshShell,WshFldrs,PathCopy;

//Создаем объект FileSystemObject

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

//Создаем файл

F=FSO.CreateTextFile("C:\\TestFile.txt", true);

//Записываем в файл строку

F.WriteLine("Тестовый файл");

//Закрываем файл

F.Close();

//Создаем объект WshShell

WshShell=WScript.CreateObject("Wscript.Shell");

//Создаем объект WshSpecialFolders

WshFldrs=WshShell.SpecialFolders;

//Определяем путь к рабочему столу

PathCopy=WshFldrs.item("Desktop")+"\\";

//Создаем объект File для файла C:\TestFile.txt

F=FSO.GetFile("C:\\TestFile.txt");

//Копируем файл на рабочий стол

F.Copy(PathCopy);

/*************  Конец *********************************************/

Замечание

Вместо метода

Сору
можно использовать метод
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. Запись информации в текстовый файл и чтение ее из него

/*******************************************************************/

/* Имя: WriteTextFile.js                      */

/* Язык: JScript                          */

/* Описание: Запись строк в текстовый файл и чтение из него     */

/*******************************************************************/

var FSO,F,TextStream,s;  //Объявляем переменные

//Инициализируем константы

var ForReading = 1, ForWriting = 2, TristateUseDefault = -2;

//Создаем объект FileSystemObject

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

//Создаем в текущем каталоге файл test1.txt

FSO.CreateTextFile("test1.txt"); 

//Создаем объект File для файла test1.txt

F=FSO.GetFile("test1.txt");

//Создаем объект TextStream (файл открывается для записи)

TextStream=F.OpenAsTextStream(ForWriting, TristateUseDefault);

//Записываем в файл строку

TextStream.WriteLine("Это первая строка");

//Закрываем файл

TextStream.Close();

//Открываем файл для чтения

TextStream=F.OpenAsTextStream(ForReading, TristateUseDefault);

//Считываем строку из файла

s=TextStream.ReadLine();

//Закрываем файл 

TextStream.Close();

//Отображаем строку на экране

WScript.Echo("Первая строка из файла test1.txt:\n\n",s);

/*************  Конец *********************************************/

Коллекция 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. Построение списка файлов

/*******************************************************************/

/* Имя: ListFiles.js                        */

/* Язык: JScript                          */

/* Описание: Получение списка всех файлов заданного каталога    */

/*******************************************************************/

//Объявляем переменные

var FSO,F,Files,WshShell,PathList,s;

//Создаем объект FileSystemObject

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

//Создаем объект WshShell

WshShell=WScript.CreateObject("Wscript.Shell");

//Создаем объект WshSpecialFolders

WshFldrs=WshShell.SpecialFolders;

//Определяем путь к папке "Мои документы"

PathList=WshFldrs.item("MyDocuments")+"\\";

//Создаем объект Folder для папки "Мои документы"

F=FSO.GetFolder(PathList);

//Создаем коллекцию файлов каталога "Мои документы"

Files=new Enumerator(F.Files);

s = "Файлы из каталога "+PathList+"\n";

//Цикл по всем файлам

for (; !Files.atEnd(); Files.moveNext()) 

 //Добавляем строку с именем файла

 s+=Files.item().Name+"\n";

//Выводим полученные строки на экран

WScript.Echo(s);

/*************  Конец *********************************************/

Объект 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

/*******************************************************************/

/* Имя: TextFile.js                         */

/* Язык: JScript                          */

/* Описание: Работа с текстовым файлом (запись и чтение информации)*/

/*******************************************************************/

var FSO,F,s;  //Объявляем переменные

var ForReading = 1; //Инициализируем константы

//Создаем объект FileSystemObject

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

//Создаем на диске C: текстовый файл TestFile.txt

F=FSO.CreateTextFile("C:\\TestFile.txt", true);

//Записываем в файл первую строку 

F.Write("Это ");

F.WriteLine("первая строка");

//Записываем в файл пустую строку

F.WriteBlankLines(1);

//Записываем в файл третью строку 

F.WriteLine("Это третья строка");

//Закрываем файл

F.Close();

//Открываем файл для чтения

F=FSO.OpenTextFile("C:\\TestFile.txt", ForReading);

//Пропускаем в файле две первые строки

F.SkipLine();

F.SkipLine();

s="Третья строка из файла C:\\TestFile.txt:\n";

//Считываем из файла третью строку

s+=F.ReadLine();

//Выводим информацию на экран

WScript.Echo(s);

/*************  Конец *********************************************/

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

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

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

Напишем сценарий 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
подставляется объект D
r
ive для нужного диска. Соответствующие объекты
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. Отчет об использовании дискового пространства для всех устройств на компьютере

/*******************************************************************/

/* Имя: DrivesReport.js                       */

/* Язык: JScript                          */

/* Описание: Формирование отчета об использовании дискового     */

/*      пространства для всех устройств на компьютере     */

/*******************************************************************/

//Объявляем переменные

var FSO, RepFile, MDate,WshShell, ForWriting = 2;

// Функция для перебора в цикле всех устройств (дисков)

function LoopDrives() {

 var Drives;

 //Создаем коллекцию дисков 

 Drives = new Enumerator( FSO.Drives );

 //Цикл по всем дискам

 for(; !Drives.atEnd(); Drives.moveNext()) WriteDriveInfo(Drives.item());

}

// Функция для вывода информации об одном устройстве (диске)

function WriteDriveInfo(drive) {

 var s,Total,Free,Used,DriveLetter,VolumeName;

 if (drive.IsReady) { //Проверяем готовность устройства

  //Вычисляем общий объем диска в мегабайтах

  Total = Math.round(drive.TotalSize/1048576);

  //Вычисляем объем свободного пространства в мегабайтах

  Free = Math.round(drive.FreeSpace/1048576);

  //Вычисляем объем использованного пространства в мегабайтах

  Used = Total - Free;

  //Определяем букву диска

  DriveLetter=drive.DriveLetter+":";

  //Определяем метку тома

  VolumeName=drive.VolumeName;

  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("+---------------------------------------------------+");

  //Записываем пустые строки

  RepFile.WriteLine();

  RepFile.WriteLine();

 } else if (drive.DriveType == 3) { //Проверяем, является ли диск сетевым

  //Записываем информацию о букве диска

  RepFile.WriteLine( "Диск " + drive.DriveLetter + " является сетевым" );

  //Записываем пустые строки

  RepFile.WriteLine();

  RepFile.WriteLine();

 } else {

  //Устройство не готово

  RepFile.WriteLine( "Устройство " + drive.DriveLetter + ": не готово" );

  //Записываем пустые строки

  RepFile.WriteLine();

  RepFile.WriteLine();

 }

}

/*******************  Начало  **********************************/

//Создаем объект FileSystemObject

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

//Открываем файл rep.txt

RepFile = FSO.OpenTextFile("rep.txt", ForWriting, true);

//Определяем текущую дату и время

MDate = new Date();

//Записываем дату и время в отчет

RepFile.WriteLine("Дата отчета: " + MDate);

RepFile.WriteLine();

//Вызываем функцию LoopDrives

LoopDrives();

//Закрываем файл rep.txt

RepFile.Close();

//Создаем объект WshShell

WshShell=WScript.CreateObject("WScript.Shell");

//Запускаем Блокнот (notepad.exe) и открываем в нем файл rep.txt

WshShell.Run("notepad.exe rep.txt");

/*************  Конец *********************************************/

// Вспомогательные функции  

//Выравнивание строки s вправо в поле длиной l символов

function RFillStr(l,s) {  

 var ss,i,ll;

 ll=l-s.length;

 if (s.length>=l) {

  return(s);

 } else {

  ss=s;

  for (i=1;i<=ll;i++) {

  ss=" "+ss;

  }

  return(ss);

 }

}

//Выравнивание строки s влево в поле длиной l символов

function LFillStr(l,s) {

 var ss,i,ll;

 ll=l-s.length;

 if (s.length>=l) {

  return(s);

 } else {

  ss=s;

  for (i=1;i<=ll;i++) {

  ss=ss+" ";

  }

  return(ss);

 }

}

//Выравнивание строки s по центру в поле длиной l символов

function FillStr(l,s) {

 var ss,i,ll,s1,l2;

 ll=l-s.length;

 if (s.length>=l) {

  return(s);

 } else {

  ss=s;

  l2=Math.round((l-s.length)/2);

  ss=LFillStr(s.length+l2,s);

  ss=RFillStr(l,ss);

  return(ss);

 }

}

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

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

Однако если хотя бы один из временных файлов будет занят каким-либо приложением, то в доступе к нему будет отказано и процесс удаления прервется (рис. 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:

/*******************************************************************/

/* Имя: DelTmp.js                          */

/* Язык: JScript                          */

/* Описание: Удаление временных файлов во всех подкаталогах     */

/*      текущего каталога                   */

/*******************************************************************/

//Объявляем глобальные переменные

var WshShell,FSO,Folder,

 ColTmp=0,     //Счетчик файлов для удаления

 ExtForDel="tmp"; //Расширение файлов, подлежащих удалению


//Рекурсивная функция для удаления временных файлов в каталоге Fold

function LoopSubFolders(Fold) {

 var SubFolders;

 //Удаляем временные файлы из каталога Fold

 DelFilesInFolder(Fold,ExtForDel);

 //Создаем коллекцию подкаталогов

 SubFolders = new Enumerator(Fold.SubFolders);

 //Цикл по всем подкаталогам

 while (!SubFolders.atEnd()) {

  //Вызываем рекурсивно функцию LoopSubFolders

  LoopSubFolders(SubFolders.item());

  //Переходим к следующему подкаталогу

  SubFolders.moveNext();

 }

}

//Функция для удаления файлов с расширением SExt в каталоге Fold

function DelFilesInFolder(Fold,SExt) {

 //Объявляем переменные

 var Files,s,SPath,FileExt,Status;

 //Создаем коллекцию всех файлов в каталоге Fold

 Files=new Enumerator(Fold.Files);

 s="";

 //Цикл по всем файлам

 while (!Files.atEnd()) {

  //Определяем путь к файлу

  SPath=Files.item().Path;

  //Выделяем расширение файла

  FileExt=FSO.GetExtensionName(SPath).toUpperCase();

  //Сравниваем расширение файла с расширением SExt

  if (FileExt==SExt.toUpperCase()) {

  ColTmp++; //Увеличиваем счетчик файлов для удаления

  try {

   Status="Ok";

   //Пытаемся удалить файл

   //Files.item().Delete();

  } catch (e) { //Обрабатываем возможные ошибки

   if (e != 0) {

   //Произошла ошибка при удалении файла

   Status="Busy";

   }

  }

  //Заменяем специальные символы в названии файла

  SPath=SPath.replace("~","{~}");

  SPath=SPath.replace("+","{+}");

  SPath=SPath.replace("^","{^}");

  SPath=SPath.replace("%","{%}");

  //Посылаем название файла и результат его удаления

  //в Блокнот

  WshShell.SendKeys(SPath+"{TAB}"+Status+"~");

  //Приостанавливаем сценарий на 0,5 сек

  WScript.Sleep(500);

  }

  Files.moveNext();  //Переходим к следующему файлу

 }

}

/*******************  Начало  **********************************/

//Создаем объект WshShell

WshShell=WScript.CreateObject("WScript.Shell");

//Запускаем Блокнот

theNotepad = WshShell.Exec("Notepad");

//Приостанавливаем сценарий на 0,5 сек

WScript.Sleep(500);

//Активизируем окно Блокнота

WshShell.AppActivate(theNotepad.ProcessID);

//Создаем объект FileSystemObject

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

//Определяем каталог, с которого будет начато удаление файлов

Folder = FSO.GetFolder("D:\\");

//Вызываем функцию LoopSubFolder для каталога Folder

LoopSubFolders(Folder);

//Формируем информацию о количестве обработанных файлов

SItog="Total: "+ColTmp+ " file(s)";

//Посылаем в Блокнот итоговую информацию

WshShell.SendKeys(SItog);

/*************  Конец *********************************************/

Поиск файлов с использованием рег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. Поиск файлов, имена которых соответствуют регулярному выражению

/*******************************************************************/

/* Имя: FindRegExp.js                        */

/* Язык: JScript                          */

/* Описание: Поиск файлов, имена которых соответствуют заданному  */

/*      регулярному выражению                 */

/*******************************************************************/

//Объявляем переменные

var WshShell,FSO,Folder,ColFind,RegExp,SFileNames;

//Функция для поиска файлов в заданном каталоге

function FindFilesInFolder(Fold,RegEx) {

 var Files,SName; //Объявляем переменные

 ColFind=0; //Счетчик найденных файлов

 SFileNames=""; //Строка с именами файлов

 //Создаем коллекцию файлов в каталоге Fold

 Files=new Enumerator(Fold.Files);

 //Цикл по всем файлам в коллекции

 while (!Files.atEnd()) {

  //Выделяем имя файла

  SName=Files.item().Name;

  //Проверяем, соответствует ли имя файла регулярному 

  //выражению

  if (RegEx.test(SName)) {

  ColFind++; //Увеличиваем счетчик найденных файлов

  //Добавляем имя файла к переменной SFileNames

  SFileNames+=SName+"\n"; 

  }

  Files.moveNext(); //Переходим к следующему файлу

 }

 SItog="Найдено файлов: "+ColFind;

 //Выводим на экран имена и количество найденных файлов

 WScript.Echo(SFileNames+SItog);

}


/*******************  Начало  **********************************/

//Создаем объект WshShell

WshShell=WScript.CreateObject("WScript.Shell");

//Создаем объект FileSystemObject

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

//Создаем объект Folder для доступа к подкаталогу ForFind

//текущего каталога

Folder = FSO.GetFolder(WshShell.CurrentDirectory+"\\ForFind");

//Создаем регулярное выражение (объект RegExp)

RegExp=new RegExp("^[ПАИ].*\.txt$","i");

//Ищем файлы, имена которых соответствуют регулярному

//выражению RegExp в каталоге Folder

FindFilesInFolder(Folder,RegExp);

/*************  Конец *********************************************/

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

Поставим перед собой следующую задачу. Пусть в заданный каталог на жестком диске (например, 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-файла

/*******************************************************************/

/* Имя: MoveLog.js                         */

/* Язык: JScript                          */

/* Описание: Перемещение файлов из каталога-источника в       */

/*      целевой каталог с ведением log-файла          */

/*******************************************************************/

//Объявляем переменные

var

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

 Dest="C:\\Out\\",  //Путь к целевому каталогу

 Mask="003",     //Расширение файлов для перемещения

 PathLog="C:\\In\\log.txt",  //Путь к log-файлу

 ForAppending=8;   //Константа для работы с файлами

//Объявляем переменные

var FSO,Fold,Files;

//Функция для записи информации в log-файл

function WriteLog() {

//Объявляем переменные

var s,ss,s1,d,File,FLog;

 WScript.Echo("");

 WScript.Echo("Записываем информацию в log-файл...");

 //Открываем log-файл для добавления

 FLog=FSO.OpenTextFile(PathLog,ForAppending,true);

 //Переходим к первому элементу коллекции файлов

 Files.moveFirst();

 //Цикл по всем файлам в коллекции

 while (!Files.atEnd()) {

  //Извлекаем текущий файл из коллекции

  File=Files.item();

  //Выделяем расширение файла

  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);

  }

  //Переходим к следующему файлу в коллекции

  Files.moveNext();

 }

} 

//Функция для перемещения файлов

function MoveFiles() {

 //Объявляем переменные

 var s,ss,Col,File;


 Col=0; //Счетчик количества перемещенных файлов

 WScript.Echo("");

 WScript.Echo("Перемещаем файлы ...");

 //Переходим к первому элементу коллекции файлов

 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("");

 WScript.Echo("Перемещено файлов:",Col); 

 WScript.Echo("Нажмите Enter...");

 WScript.StdIn.ReadLine();

}

/*******************  Начало  **********************************/

//Создаем объект 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();

}

//Создаем объект Folder для каталога-источника

Fold=FSO.GetFolder(Source);

//Создаем объект Enumerator для доступа к коллекцию файлов 

//в каталоге-источнике

Files=new Enumerator(Fold.Files);

//Записываем информацию в log-файл

WriteLog();

//Перемещаем файлы в целевой каталог

MoveFiles();

/*************  Конец *********************************************/

// Вспомогательные функции  

//Дополнение строки ss ведущими нулями до длины ll

function LeadZero(ll,ss) {

 var i,s,l1;

 s=ss.toString();

 l1=s.length;

 if (l1<=ll) {

  for (i=1;i<=ll-l1;i++) s="0"+s;

 }

 return(s);

}

//Формирование из объекта Date строки формата ДД/ММ/ГГГГ 

function DateToStr(dd) {

 var s;

 s=LeadZero(2,dd.getDate())+"/";

 s+=LeadZero(2,dd.getMonth()+1)+"/";

 s+=dd.getYear();

 return(s);

}

//Формирование из объекта Date строки формата ЧЧ:ММ 

function TimeToStr(dd) {

 var s;

 s=LeadZero(2,dd.getHours())+":"+LeadZero(2,dd.getMinutes());

 return(s);

}

//Выравнивание строки s влево в поле длиной l символов

function LFillStr(l,s) {

 var ss,i,ll;

 ll=l-s.length;

 if (s.length>=l) {

  return(s);

 } else {

  ss=s;

  for (i=1;i<=ll;i++) {

  ss=ss+" ";

  }

  return(ss);

 }

}

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

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

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

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

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

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

Потапов|Сергей|55-55-55|Моховая|3|10|Без примечаний

Попов|Андрей|56-56-56|Ленина|3|5|Без примечаний

Иванов|Иван|17-17-17|Садовая|4|6|Очень хороший человек

Казаков|Сергей|24-19-68|Полежаева|101|22|Тоже очень хороший человек

Ниже приведен сценарий 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

 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. Вывод содержимого записной книжки с сортировкой по фамилии

/*******************************************************************/

/* Имя: SortName.js                         */

/* Язык: JScript                          */

/* Описание: Записная книжка (данные в текстовом файле book.txt).  */

/*      Вывод всех записей с сортировкой по фамилии      */

/*******************************************************************/

//Объявляем переменные

var 

 WshShell,FSO, 

 BasePath,  //Путь к текущему каталогу

 PathBook,  //Путь к файлу с данными

 PathOut,  //Путь к выходному файлу

 FBook,   //Файл с данными

 FOut,    //Выходной файл

 NomRec=0,  //Счетчик количества записей

 PersonRec, //Объект для хранения данных об одном человеке

 PersonArr; //Массив для хранения объектов PersonRec

//Инициализируем константы для работы с файлами

var  

 ForReading=1,

 ForWriting=2;


//Конструктор объекта 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;     //Примечание

}

//Заполнение нового элемента массива

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 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();

}

//Запись в выходной файл итоговой информации

function TopReport(Mess) {

 FOut.WriteLine(Mess);

 FOut.WriteLine("--------------------");

 FOut.WriteLine("");

}

//Запись в выходной файл итоговой информации

function BottomReport() {

 FOut.WriteLine("Всего записей: "+NomRec);

}

//Запись данных из объекта Person в выходной файл

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++;

}

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

function ListPersonArray() {

var i;

 //Сортировка массива по фамилии

 PersonArr.sort(SortLastName);

 //Цикл по всем элементам массива PersonArr

 for (i=0;i<=PersonArr.length-1;i++) {

  //Запись информации в выходной файл

  PrintPerson(PersonArr[i]);

 }

}

//Функция для сортировки массива по фамилии

function SortLastName(Pers1,Pers2) {

 if (Pers1.LastName

 else if (Pers1.LastName==Pers2.LastName) return 0;

 else return 1;

}


//Вывод содержимого файла с данными                      

function ListFile() {

 //Считывание данных из файла в массив

 FileToArray();

 //Запись информации из массива в выходной файл

 ListPersonArray();

}

//Просмотр содержимого выходного файла в Блокноте

function MakeOut() {

 //Закрываем выходной файл

 FOut.Close();

 //Открываем выходной файл в Блокноте

 WshShell.Run("notepad "+PathOut,1);

}

//Построение путей к файлам

function InitPath() {

 BasePath=WshShell.CurrentDirectory+"\\";

 //Путь к файлу с данными

 PathBook=BasePath+"book.txt",

 //Путь к выходному файлу

 PathOut=BasePath+"out.txt";

}

//Основная запускная функция

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();

}

/*******************  Начало  **********************************/

Main();

/*************  Конец *********************************************/

Загрузка...