GO BACK

Windows Scripting Host教室 その3


「特別なフォルダとコレクション操作」



■「My Documents」フォルダ内のファイルを調べる


 前回作ったスクリプトは、いずれも「パスを指定してオブジェクトを得る」というやり方のものでした。これはこれで利用価値は高いのですが、「パスがあっていないと動かない」という大きな欠点があります。

 まあ、自分が作ったファイルを操作するような場合は、これでもいいでしょう。面倒ですが、他にやりようがありませんから。けれど、Windows固有のフォルダやファイルなどを操作する時は、もうちょっと違ったやり方ができると便利です。

 例えば、「Windows」フォルダや「My Documents」フォルダ、デスクトップといったものを操作したい場合、いちいちパスを指定してやるのはスマートではありません。また、人によっては「My Documents」フォルダの場所を変更している人や、「Windows」フォルダを別の名前でインストールしている人もいるかも知れません。こうした場合でも問題なく動くようなスクリプトが作れれば、スクリプトの利用範囲はぐっと広がります。フリーウェアのように、「誰でもどんなマシンでも使えるスクリプト」が増えれば、みんなの役に立ちますね。

 そこで、まずは「特別なフォルダ」を扱う方法から覚えていきましょう。――WSHには、Windowsに用意されている特別なフォルダのパスを調べる機能があります。これは、「Shellオブジェクト」というオブジェクトの中に用意されています。このオブジェクトは、以下のようにして作ります。

	Set 《変数》 = CreateObject("WScript.Shell")

 これで、《変数》にShellオブジェクトが設定されます。このShellオブジェクトは、Windows全体の状態などを扱うためのオブジェクト、と考えるとよいでしょう。このオブジェクトの中に、「SpecialFolders」という命令があります。これが、Windowsで使われている特別なフォルダを調べるためのものなのです。

 とりあえず、実際に何かサンプルを動かしてみましょう。――簡単な例として、「マイドキュメント」フォルダの容量と最終アクセス日を表示するスクリプトを考えてみます。

Set WSell = CreateObject("WScript.Shell")
MyDoc = WSell.SpecialFolders("MyDocuments")
Set FS = CreateObject("Scripting.FileSystemObject")
Set F = FS.GetFolder(MyDoc)
str = F.Name & vbCrLf
str = str & "サイズ:" & F.Size & vbCrLf
str = str & "アクセス日:" & F.DateLastAccessed
MsgBox str


 こんな感じになります。実行すると「マイドキュメント」フォルダの場所を調べてサイズと最終アクセス日を表示します。これは「マイドキュメント」フォルダのパスを変更したりしても関係なく、常に現在の「マイドキュメント」フォルダの状態を調べてくれるという点がミソです。

 ここで行なっていることを見てみましょう。まず、CreateObjectで変数WSellにShellオブジェクトを設定していますね。そして次の「WSell.SpecialFolders("MyDocuments")」という部分が、「マイドキュメント」フォルダのパスを調べている部分です。このように、

	《変数》 = 《Shell》.SpecialFolders("《フォルダの指定》")

――と実行することで、Windowsの特別なフォルダのフルパスのテキストを変数に取り出すことができます。

 これができれば、後は前回やったことですね。FileSystemObjectオブジェクトを作成し、GetFolderで得られた「マイドキュメント」フォルダのパスを使ってFolderオブジェクトを取り出します。そしてプロパティを調べてMsgBoxで表示しておしまい!です。

 このようにSpecialFolders命令自体は簡単ですね。問題は、《フォルダの指定》の部分です。ここでは得たい特別なフォルダの名前をテキストで設定する必要があります。ですから、どんな名前が用意されているのかを知っておく必要がありますね。

Desktop――デスクトップを示すフォルダ
Favorites――「お気に入り」フォルダ
Fonts――フォントフォルダ
MyDocuments――「マイドキュメント」フォルダ
Programs――「スタート」ボタンの「プログラム」フォルダ
Recent――「最近使ったファイル」のフォルダ
SendTo――右ボタンクリックで現れる「送る」メニューのためのフォルダ
StartMenu――「スタート」ボタンのためのフォルダ
StartUp――「スタート」ボタンの「スタートアップ」フォルダ

 ざっとまとめるとこうなります。これだけ特別なフォルダが使えるようになると、結構実用的なスクリプトが作れそうですね。――例えば、「最近使ったファイル」をクリアするスクリプト、なんてどうでしょう?

Set WSell = CreateObject("WScript.Shell")
Rec = WSell.SpecialFolders("Recent")
Set FS = CreateObject("Scripting.FileSystemObject")
FS.DeleteFile Rec & "*.*"
MsgBox "「最近使ったファイル」をクリアしました。"

 これでOK。実に簡単です。ポイントは、削除するDeleteFile命令の部分。ここではSpecialFoldersで得られたパスを利用して「FS.DeleteFile Rec & "*.*"」という形で実行しています。

 MS-DOSのバッチを書いた人なら知っているでしょうが「*」というのはワイルドカードと呼ばれる記号で、「全ての文字の代りになる記号」ということです。SpecialFoldersで「最近使ったファイル」フォルダのパスが得られますから、これに「\*.*」とつなげることで、フォルダ内の全てのファイルを指定するワイルドカードを使ったパスが得られます。それで、フォルダ内の全ファイルが一発で削除できる、というわけです。



■Files/SubFoldersコレクションを使う


 このワイルドカードを使った方法はなかなか便利ですが、きめ細かな操作ができないのが欠点です。先に触れたように、ファイルのコピーや削除といったものはパスを指定してダイレクトに実行できますが、ファイルのプロパティを扱うなどそれ以上の操作は、そのファイルやフォルダのオブジェクトを作って操作してやらないといけません。

 ですから、今のように「フォルダの中の全ファイルを操作する」というようなスクリプトも、単純なファイルのコピー/移動/削除以外は、いちいちフォルダ内の全てのファイルのオブジェクトを作っては操作し…ということをやらないといけなくなります。そこで、次に「フォルダ内のファイルやフォルダのオブジェクトをまとめて扱う」という方法を覚えることにしましょう。

 これは、実は意外に簡単です。Folderオブジェクトの中には、そのフォルダ内にあるファイル/フォルダをまとめて扱う機能が用意されているからです。それは「Files」「SubFolders」というものです。

 これも、簡単なサンプルを作って見ましょう。「マイドキュメント」フォルダ内のファイルとフォルダの数を表示するスクリプトです。

Set WSell = CreateObject("WScript.Shell")
MyDoc = WSell.SpecialFolders("MyDocuments")
Set FS = CreateObject("Scripting.FileSystemObject")
Set F = FS.GetFolder(MyDoc)
str = "My Documentsフォルダ" & vbCrLf
str = str & "ファイル数:" & F.Files.Count & vbCrLf
str = str & "フォルダ数:" & F.SubFolders.Count
MsgBox str


 これを実行したところが上の図です。ちゃんとファイルとフォルダの数がわかるでしょう? ここでは、こんな形でファイルとフォルダの数を取り出しています。

str = str & "ファイル数:" & F.Files.Count & vbCrLf
str = str & "フォルダ数:" & F.SubFolders.Count

 Fというのは、FileSystemObjectで取り出された「マイドキュメント」フォルダのFolderオブジェクトですね。そして「Files」「Folders」というのが、Folderオブジェクト内の全ファイル/全フォルダを示すものです。これは「コレクション」といって、全ての項目を持ったリストのようなものが入っているのだ、と考えるとよいでしょう。

 その後にある「Count」というのは、コレクションの要素数を示すプロパティです。複数の要素を持ったコレクションにはたいてい用意されています。つまり「F.Files.Count」というもので、Folderオブジェクト内の全ファイルの数が得られていたのですね。



■コレクションを操作する「For Each」構文


 では、こうしてFiles/SubFoldersコレクションで得られたものは、どうやって処理すればいいんでしょう。1つ1つオブジェクトを調べていくのは結構しんどそうです。

 が! 心配御無用。実はVBScriptには、コレクションの処理に最適な構文が用意されているのです。それが「For Each」というもの。これは繰り返し構文の一種ですが、いくつもの要素全てに処理を行なうような場合に最適なのです。

 では、簡単な例を作りましょう。「マイドキュメント」フォルダの中にあるファイルを、全てCドライブの「Backup」というフォルダの中にコピーする、というスクリプトを考えてみましょう。

Set WSell = CreateObject("WScript.Shell")
MyDoc = WSell.SpecialFolders("MyDocuments")
Set FS = CreateObject("Scripting.FileSystemObject")
Set F = FS.GetFolder(MyDoc)
For Each Obj In F.Files
	Obj.Copy "c:Backup"
Next
MsgBox "終わりました。"

 全ファイルをまとめて処理するにしては、意外に簡単そうですね。――ここでは、今までのスクリプトと同様、SpecialFoldersで「マイドキュメント」のパスを得てGetFolderした後、For Each構文の処理を行なっています。――この構文は、

For Each《変数》In《コレクション》
	……実行する命令……
Next

このような形で記述します。すると、《コレクション》の要素を1つずつ順番に取り出しては《変数》に設定し、以下の命令を繰り返し実行するのです。ですから、この構文の中で《変数》のオブジェクトを処理するような命令を書いてやれば、この《変数》に次々にオブジェクトが設定され処理されますから、結果的に構文を抜ける時にはコレクション全てのオブジェクトに同じ処理が施されることになるわけです。

 また、ここでは構文内の部分で「Obj.Copy "c:Backup"」というものを実行しています。この「Copy」というのは、Fileオブジェクトに用意されているコピーのための命令なのです。

 今まで、FileSystemObjectにある「CopyFile」「MoveFile」「DeleteFile」といった命令を使ってきましたが、File/Folderオブジェクトの中にも全く同じ働きの命令が用意されています。これらは、以下のようなものです。

《File/Folder》.Copy 《コピー先のパス》
《File/Folder》.Move 《移動先のパス》
《File/Folder》.Delete

 これらは、このように使います。パラメータがそれぞれ1つずつ少なくなっている点が違いますね。コピー/移動元のパスは指定する必要がないのです。なぜって、そのファイル/フォルダのオブジェクトの中に命令が用意されているのですから、指定する必要などないでしょう?



■ファイル/フォルダの存在チェック


 今回登場したような特別なフォルダは、SpecialFoldersでパスを調べて処理できますが、それ以外のファイルやごく一般的なファイルは、やはりパスをユーザーから入力してもらって処理するような形になります。この場合、入力したパスが間違っていたりするとすぐにエラーが起きてしまいます。

 こうしたエラーを防ぐには、まず最初に入力されたパスにファイル/フォルダが存在するかどうか調べ、あることを確認した上で処理を実行するようにしておくとよいでしょう。このための命令が、FileSystemObjectにちゃんと用意されているのです。それは「FileExists」「FolderExists」というものです。

 これも、サンプルを作ってみましょう。以下は、入力したパスのファイルの作成日/修正日/アクセス日を調べて表示するスクリプトです。

Set FS = CreateObject("Scripting.FileSystemObject")
FPath = InputBox("ファイルのパスを入力:")
If FS.FileExists(FPath) Then
	Set F = FS.GetFile(FPath)
	str = F.Name & vbCrLf
	str = str & "作成日:" & F.DateCreated & vbCrLf
	str = str & "修正日:" & F.DateLastModified & vbCrLf
	str = str & "アクセス日:" & F.DateLastAccessed & vbCrLf
	MsgBox str
Else
	MsgBox "「" & FPath & "」というファイルは、存在しません。"
End If


 最初にパスを尋ねてくるのでここでテキストでパスを入力します。もしそのパスのファイルがあれば、プロパティを調べて表示します。が、もし存在しなかったら、その旨を報告してきます。

 ここでは、パスの入力後、「If FS.FileExists(FPath) Then」という条件文で、そのパスのファイルがあるかどうかチェックしています。このようにFileExistsは、パラメータでパスのテキストを指定すると、そのパスのファイルが存在するかどうか調べ、存在すればTrue、しなければFalseという値を返します。

 このTrue/Falseという値は「Boolean(ブーリアン)」値といって、正しいか正しくないかというものを示すのに使われるものです。本来なら、If FS.FileExists(FPath) = True Then」と書くのが正しいように思えますが、このBoolean値の場合は、「Trueは正しい」と判断してくれるので、「= True」を省略してもいいことになってます。

 「FolderExists」も、使い方はFileExistsと全く変わりません。実際に簡単なスクリプトを書いてみれば、これらの働きはすぐにわかることでしょう。


GO NEXT


GO HOME