Hey, Scripting Guy!

Scripting Guys が皆さんの質問にお答えします

Hey, Scripting Guy!

TechNet コラムへようこそ。このコラムでは、よく寄せられるシステム管理スクリプトに関する質問に Scripting Guys がお答えします。システム管理スクリプトについて質問がある場合は、scripter@microsoft.com (英語のみ) までお送りください。すべての質問に回答することはできないかもしれませんが、可能な限り対応いたします。

詳細情報

Hey, Scripting Guy! カテゴリ別アーカイブ

Hey, Scripting Guy! 日付別アーカイブ

Hey, Scripting Guy! ダウンロード

Spacer

*

一連のフォルダ内のファイル数が指定した値より多いかどうか確認する方法はありますか

Hey, Scripting Guy! Question

Scripting Guy さん、よろしくお願いします。一連のフォルダ内のファイル数が、指定した値より多いかどうか確認する方法はありますか。

-- DP

SpacerHey, Scripting Guy! AnswerScript Center

DP さん、こんにちは。Buongiorno. Le come sta? Tutto bene?

これはどういう意味でしょうか。Io non so; Io non parlo Italiano. つまり、こういうことです。わかりません。イタリア語は話せないのです。

いえ、本当は、Io non so; Io non parlo Italiano が、「わかりません。イタリア語は話せないのです」という意味です。最初の文については、(少なくとも私たちが) 翻訳すると次のようになります。「こんにちは。お元気ですか。万事順調ですか」

さて、なぜ突然イタリア語に興味を持ったのかというと、皆さんがこのコラムを読んでいる間も、このコラムを執筆している Scripting Guy はイタリアへ飛び立ち、ローマとベネチアで 10 日間の休暇を過ごす準備をしているからです。数年前、このコラムを執筆している Scripting Guy は、ロンドンとパリに家族を何人か連れて行きました。旅行はとても楽しかったのですが、行き先、やること、食事などについて多種多様でばらばらな家族の意見をまとめるのは本当に疲れることだとわかりました。家に帰ると、彼は「楽しかったよ。でも二度とこんなことはしないぞ」と言いました。

なのに、言うまでもありませんが、彼はまた "こんなこと" をしています。さらに、よくいる無知なアメリカ人旅行者に見えないように、イタリア語の単語もいくつか覚えようとしています (明らかに彼はよくいる無知なアメリカ人旅行者ですが、彼はそういった旅行者に見えないようにしたいだけなのです)。

最初は、このコラムを執筆している Scripting Guy は、今日のコラムを全部イタリア語で書こうと考えていました。ところが、書店で買ったイタリア語の独習書には、「Associators Of クエリを使用して指定したフォルダ内のすべてのサブフォルダのコレクションを取得する」などの表現に対応するイタリア語が載っていませんでした。でも、その方が良かったのでしょう。そもそも、このコラムは英語で書いた場合でもわかりにくいことがあります。イタリア語で書こうとした場合には、さらに難解になるのは言うまでもありません。

では、DP さん、あなたの問題を解決するスクリプトを英語で (ここでは、それを日本語に翻訳して) 紹介します。

strComputer = "."

Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")

Set colSubfolders = objWMIService.ExecQuery _
    ("Associators of {Win32_Directory.Name='C:\Absentee Reports'} " _
        & "Where AssocClass = Win32_Subdirectory " _
            & "ResultRole = PartComponent")

For Each objFolder in colSubfolders
    Set colFiles = objWMIService.ExecQuery _
        ("ASSOCIATORS OF {Win32_Directory.Name='" & objFolder.Name & "'} Where " _
            & "ResultClass = CIM_DataFile")

    If colFiles.Count => 4 Then 
        Select Case colFiles.Count
            Case 4
                Wscript.Echo objFolder.Name & " has 4 files in it."
            Case 5
                Wscript.Echo objFolder.Name & " has 5 files in it."
            Case 6
                Wscript.Echo objFolder.Name & " has 6 files in it."
            Case 7
                Wscript.Echo objFolder.Name & " has 7 files in it."
            Case 8
                Wscript.Echo objFolder.Name & " has 8 files in it."
        End Select
    End If
Next

ご覧のとおり、まずローカル コンピュータの WMI サービスに接続します。でも、心配しないでください。このスクリプトはリモート コンピュータに対しても同じくらい簡単に実行できます。スクリプトをリモート コンピュータに対して実行するには、次のように、リモート コンピュータの名前を strComputer 変数に代入するだけです。

strComputer = "atl-fs-01"

DP さんによると、サーバーのうちの 1 台にフォルダが格納されていて (この例では、C:\Absentee Reports)、このフォルダには組織の各従業員用のサブフォルダがあります。つまり、次のようなフォルダ構造になっています。

C:\Absentee Reports 
C:\Absentee Reports\Gail Erickson 
C:\Absentee Reports\Jonathan Hass 
C:\Absentee Reports\Ken Myer 
C:\Absentee Reports\Pilar Ackerman

従業員が仕事を休むたびに、欠勤の詳細を記した新しい文書が当該従業員のサブフォルダに追加されます。たとえば、Ken Myer が欠勤した場合、新しい文書がサブフォルダ C:\Absentee Reports\Ken Myer に追加されます。必要な作業は、これらのサブフォルダ内を 1 つずつ確認して、各サブフォルダにある文書の数を数え、文書の数に応じた処理を実行することです。良い質問ですね。一体どうやってこのような処理を実行するのでしょうか。

まず、次のコード行を使用して C:\Absentee Reports 内のすべてのサブフォルダのコレクションを返します。

Set colSubfolders = objWMIService.ExecQuery _
    ("Associators of {Win32_Directory.Name='C:\Absentee Reports'} " _
        & "Where AssocClass = Win32_Subdirectory " _
            & "ResultRole = PartComponent")

いえ、これはイタリア語ではありません。たとえこのコラムを執筆している Scripting Guy が書いたイタリア語だとしても、イタリア語はもっとわかりやすいはずです。このおかしな見た目のコードはイタリア語ではなく、Associators Of クエリです。好む好まざるとにかかわらず、このクエリは上記のような形式で書くことになっています。でも、細かい点について心配する必要はありません。ただ、親フォルダである C:\Absentee Reports のサブフォルダ (Win32_Subdirectory クラスのインスタンス) のコレクションを取得しているということを理解してください。また、このクエリでは親フォルダの直下のフォルダのみが返されることに注意してください。入れ子になったサブフォルダ (サブフォルダ内のサブフォルダ) がある場合は、他の方法でサブフォルダとその内部のサブフォルダを取得する必要があります。

クエリを発行して C:\Absentee Reports 内のすべてのサブフォルダのコレクションが返されたら、次の手順では、このコレクション内のすべてのフォルダを処理する For Each ループを設定します。このループでは、まず、さらにもう 1 つクエリを発行します。このクエリでは、最初のサブフォルダ内のすべてのファイルで構成されるコレクションが返されます。

Set colFiles = objWMIService.ExecQuery _
    ("ASSOCIATORS OF {Win32_Directory.Name='" & objFolder.Name & "'} Where " _
        & "ResultClass = CIM_DataFile")

そうです。これもおかしな (pazzesco) Associators Of クエリです。とにかく、コレクションの最初のサブフォルダが、Gail Erickson という名前のフォルダだとしましょう。つまり、このフォルダの Name プロパティ (もっと一般的には、ファイル パスと呼ばれます) は、C:\Absentee Reports\Gail Erickson になります。したがって、この Associators Of クエリでは、(objFolder.Name 変数で表されている) C:\Absentee Reports\Gail Erickson フォルダに関連付けられた (格納された) CIM_DataFile クラスのすべてのインスタンスを要求しています。つまり、C:\Absentee Reports\Gail Erickson フォルダに接続して、このフォルダ内のすべてのファイル (CIM_DataFile クラスのインスタンスであるファイル) のコレクションを返します。

後は簡単 (facile) です。すべての WMI コレクションには、コレクション内の項目数を示すプロパティ (Count) があります。フォルダ内のファイル数が 4、5、6、7、8 のいずれの値かに応じて、異なる処理を実行する必要があります。フォルダのファイル数が 4 未満の場合は、何も行いません。したがって、コレクションが返されたら、Count プロパティの値を調べて、この値が 4 以上かどうかを確認します。

If colFiles.Count => 4 Then

4 以上の場合は、Count プロパティの値に基づいた Select Case ステートメントを設定します。

Select Case colFiles.Count
    Case 4
        Wscript.Echo objFolder.Name & " has 4 files in it."
    Case 5
        Wscript.Echo objFolder.Name & " has 5 files in it."
    Case 6
        Wscript.Echo objFolder.Name & " has 6 files in it."
    Case 7
        Wscript.Echo objFolder.Name & " has 7 files in it."
    Case 8
        Wscript.Echo objFolder.Name & " has 8 files in it."
    Case Else
        Wscript.Echo objFolder.Name & " has more than 8 files in it."
End Select

ご覧のとおり、ここでは特に変わったことはしていません。たとえば、Count プロパティの値が 4 の場合は、フォルダに 4 つのファイルがあることを示すメッセージをエコー バックするだけです。それほど刺激的ではありませんが、それはどうでもよいことです。重要なのは、フォルダ内のファイル数を確認し、ファイル数に応じて特定の処理を実行する方法を説明することです。もちろん、もう少し凝った (それにもう少し意味のある) 処理を実行するのに必要な作業は、このサンプル コードをもう少し凝った (それにもう少し意味のある) コードに置き換えるだけです。

ここからは、ループ処理の先頭に戻り、コレクション内の次のサブフォルダについても同じ処理を繰り返します。最終的には、次のようなレポートが返されます。

C:\Scripts\Ken Myer has 6 files in it. 
C:\Scripts\Pilar Ackerman has 6 files in it.

これで完了 (fatto) です。

少なくとも、私たちは fatto (ファット) が "完了" という意味だと思っています。ちょっとしたコメディアンを気取っている Scripting Guy の息子はきっと、fatto のことを "完了" ではなく父親のおなか周りを表す言葉だと思っているでしょう。

息子よ、そのとおりだ。ははは。

これでご質問の回答になっているとよいのですが、DP さん。本当は、もう少し時間をとってこの質問についてもっと詳しく説明したいのですが、このコラムを執筆している Scripting Guy はそろそろ空港 (aeroporto) に行かなくてはなりません。でも、がっかりしないでください。彼が留守の間も、毎日新しい Hey, Scripting Guy! コラムを公開することをお約束します。休暇中なのになぜこれほど働いているのでしょうか。答えは簡単で、それは彼が・・・。うーん。

今考えてみれば、この疑問の答えは本当に 1 つしかありません。それは、このコラムを執筆している Scripting Guy が特別 astuto (賢い) わけではないということです。

これについては、Scripting Guy の息子 (もちろん編集者も) が何年も前にお伝えしていることかもしれませんが。

まあ、なるようになるでしょう。では皆さん、arrivederci (さようなら)。


ページのトップへページのトップへ