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 さん、よろしくお願いします。あるフォルダに格納されているすべての .JPG ファイルの名前を変更して、ファイル名に写真の撮影日が含まれるようにする方法はありますか。

-- NH

SpacerHey, Scripting Guy! AnswerScript Center

NH さん、こんにちは。Hey, Scripting Guy! へようこそ。このコラムは、TechNet で公開されているスクリプト関連の日刊コラムの中で唯一、ステロイド、アンフェタミン、ヒト成長ホルモンなどの人工的な増強剤を使用せずに執筆されているコラムです。このコラムを執筆している Scripting Guy は、毎朝大掛かりな薬物検査を受けていますが、今のところ、どの検査でも陰性と診断されています。Hey, Scripting Guy! は、自然界の思し召しに従って執筆されたコラムです。

大変興味深いことに、編集者は、Hey, Scripting Guy! がステロイド、アンフェタミン、ヒト成長ホルモンなどの人工的な増強剤を使用しないで執筆されていることにずっと失望しています。彼女には、「つまらないコラムね。「もう少し盛り上げるために何かしなさいよ。昨日のコラムの始まりなんて、"今日はおもしろい話は何もありません" と言っているようなものじゃない。そんなものをだれが読みたいと思うの。ステロイドを使う気がないなら、せめて何かしなさい。わかったわね」と言われました。

編集者注 : 1 つ言っておきますが、決して編集者は薬物を使用して能力を上げたり下げたり維持したりすることを推奨しているわけではなく、おもしろく、かつステロイドやアンフェタミン (これは単なる一例ですが) といった話をして弁護士 (さらにひどい場合は弊社の経営陣) から目を付けられないようなコラムを執筆してほしいと思っているだけです。

編集者に対しては敬意を持っていますが、この考えには賛成しかねます。"盛り上げなさい" とはどういうことでしょうか。熱心な読者の皆さんはご存知だと思いますが、私たちはほぼ毎回、Scripting Guy の息子と彼が所属する野球チームについてのおもしろい話を紹介しています。もう十分盛り上がっていると思いませんか。

そして、このコラムを執筆している Scripting Guy は、おもしろい話が何もない日がときどきあっても、また仮におもしろい話が一年中なくても、ステロイド、アンフェタミン、ヒト成長ホルモンなどの人工的な増強剤を使用することは断固として拒否します。なぜ拒否するのでしょうか。それは、ちょっとした刺激が必要なときは次のようなスクリプトを作成すれば済むからです。

On Error Resume Next

Set objFSO = CreateObject("Scripting.FileSystemObject")

Set objConnection = CreateObject("ADODB.Connection")
Set objRecordSet = CreateObject("ADODB.Recordset")

objConnection.Open "Provider=Search.CollatorDSO;Extended Properties='Application=Windows';"

objRecordSet.Open "SELECT System.ItemPathDisplay, System.Photo.DateTaken FROM SYSTEMINDEX Where System.ItemFolderPathDisplay = 'C:\Test'", _
    objConnection

objRecordSet.MoveFirst

Do Until objRecordset.EOF
    strName = objRecordset.Fields.Item("System.ItemPathDisplay")
    arrName = Split(strName, ".")

    dtmPhotoDate = objRecordset.Fields.Item("System.Photo.DateTaken")
    strDay = Day(dtmPhotoDate)
    strMonth = Month(dtmPhotoDate)
    strYear = Year(dtmPhotoDate)
    strNewName = arrName(0) & "_" & strMonth & "_" & strDay & "_" & strYear & "." & arrName(1)
    
    objFSO.MoveFile strName , strNewName
    objRecordset.MoveNext
Loop

ああ、このスクリプトを見たら頭がグルグル回って心臓がドキドキしてしてきました。

興奮が収まるまで少し時間をください。収まったらこのスクリプトのしくみについて説明します。ですが、このスクリプトのしくみを説明する前に、1 つ注意していただきたいことがあります。それは、ファイルをディスク ドライブに保存すると、必ずデジタル写真の撮影日も保存されるということです。この日付を確認するには、エクスプローラかマイ コンピュータを開き、ファイルを右クリックして、[プロパティ] をクリックします。次に、[概要] タブをクリックし、[詳細設定] をクリックします (Windows Vista の場合は、ファイルを右クリックし、[プロパティ] をクリックして、[詳細] タブをクリックします)。これは良い知らせです。では悪い知らせは何かというと、Windows Vista 以前のオペレーティング システムには、スクリプトからこの情報にアクセスできる機能が組み込まれていないということです。FileSystemObject や WMI を使用すると、そのファイルが作成された日付 (つまりファイルがドライブに保存された日付) を特定することはできますが、写真の撮影日を特定する方法はありません。1 つもです。

では、どのようにして、デジタル写真の撮影日を特定し、その日付をファイル名に追加できるスクリプトを作成したのでしょうか。答えは簡単です。ステロイドです。

失礼、これは冗談です。実際は、ステロイドではなくデスクトップ サーチ 3.0 を使用しました (私たちはいつもこの 2 つを混同してしまいます)。確かに、デスクトップ サーチ 3.0 を使用するには、このソフトウェアをダウンロード、インストール、および構成する必要があります (ただし、Windows Vista を実行している場合は、このテクノロジがオペレーティング システムに含まれているため、このような作業は必要ありません)。これは面倒な作業かもしれません。多くの皆さんは、このような新しいコンポーネントをダウンロードしてインストールするのに消極的であることも十分承知しています。そうは言っても、デスクトップ サーチ 3.0 はかなりの優れものです。それに、他に今回の問題を解決する方法は思い付きません。

今回はデスクトップ サーチ テクノロジについては詳しく説明しませんが、このテクノロジの詳細とそのしくみについては、私たちが執筆した「Seek and Ye Shall Find」という記事を参照してください。簡単に説明すると、デスクトップ サーチは、コンピュータ上の指定のフォルダとデータ ストアにインデックスを作成 (もちろん、インデックスの作成対象は完全に制御できます) した後、ADO (ActiveX Data Objects) を使用してその情報を公開します。これはどういうことかというと、単純なデータベース スクリプトを記述し、標準的な SQL クエリを使用して、あらゆるすばらしい操作を実行できるということです。たとえば、デジタル写真の撮影日を特定できます。

では、デジタル写真の撮影日を特定するにはどうすればよいでしょうか。まず、Scripting.FileSystemObject オブジェクトのインスタンスを作成します。このオブジェクトは、ファイル名を変更するときに使用します。その後、ADODB.Connection データベース オブジェクトと ADODB.Recordset データベース オブジェクトのインスタンスを作成し、次のコードを使用してデスクトップ サーチのデータ ストアにバインドします。

objConnection.Open "Provider=Search.CollatorDSO;Extended Properties='Application=Windows';"

ちなみに、初期設定と構成を行うための部分は定型的に使用されるため、この部分のコードは、デスクトップ サーチを使用する他のスクリプトでも、ほぼそのまま使用できます。変更する必要があり、注目する必要がある部分は、次の SQL クエリです。

objRecordSet.Open "SELECT System.ItemPathDisplay, System.Photo.DateTaken FROM SYSTEMINDEX Where System.ItemFolderPathDisplay = 'C:\Test'", _
    objConnection

このクエリについても、今日のコラムでは詳しく説明しません。デスクトップ サーチのシステム インデックスから情報を要求していると言えば十分でしょう。どのような情報を要求しているかというと、System.ItemPathDisplay と System.Photo.DateTaken という 2 つのプロパティの値です (前者はファイルのパスですが、後者については説明しなくてもおわかりいただけますよね)。もちろん、コンピュータ上のすべてのファイルからこの情報を取得する必要はありません (必要であれば取得することもできますが)。必要なのは、C:\Test フォルダにあるファイルのプロパティの値のみです。Where 句はこのために使用しています。この句を使用することによって、System.ItemFolderPathDisplay プロパティの値 (フォルダのパス) が C:\Test に設定されている項目のデータのみを取得できます。

Open コマンドでは、C:\Test フォルダに格納されているすべてのファイルのパスと写真の撮影日に関するデータから構成されたレコードセットを取得しています。写真の撮影日を各ファイル名に追加するには、次のように EOF (ファイルの末尾) プロパティの値が True に設定されるまで実行される Do Until ループを使用して、これらのファイルを 1 つずつ処理する必要があります。

Do Until objRecordset.EOF

では、このレコードセットに対してどのような処理を実行すればよいでしょうか。まず、次のように、レコードセットの 1 つ目のファイルからパスを取得し、その値を strName という名前の変数に格納します。

strName = objRecordset.Fields.Item("System.ItemPathDisplay")

つまり、strName 変数には C:\Test\100_0011.JPG のような値が格納されるということです。今回は写真の撮影日をファイル名の末尾に追加することにしたため、新しいファイル名は C:\Test\100_0011_8_3_2007.JPG のようになります (もちろん、写真の撮影日が 2007 年 8 月 3 日の場合です)。このことを念頭に置き、次のように Split 関数を使用して、ファイルのパスを取得し、そのパスを arrName という名前の配列に変換します。

arrName = Split(strName, ".")

ドットで区切る (ファイル名にはドットが 1 つのみ含まれていることを前提としています) ことによって、次の要素から構成される配列が作成されます。

C:\Test\100_0011

JPG

これが本当にファイル名を変更する作業に役立つかどうかは、すぐにわかります。

しかし、まずは次のように、写真の撮影日を取得し、その日付を dtmPhotoDate という名前の変数に格納する必要があります。

dtmPhotoDate = objRecordset.Fields.Item("System.Photo.DateTaken")

その後、次のコード (VBScript の Day、Month、および Year 関数) を使用して、写真の撮影日を日 (3)、月 (8)、および年 (2007) に分解し、それぞれを変数に格納します。

strDay = Day(dtmPhotoDate)
strMonth = Month(dtmPhotoDate)
strYear = Year(dtmPhotoDate)

おわかりいただけたでしょうか。そうですか、よかったです。では、次のコードもそれほど問題なく理解できるでしょう。

strNewName = arrName(0) & "_" & strMonth & "_" & strDay & "_" & strYear & "." & arrName(1)

このコードでは、次の要素から構成される新しいファイルのパスを作成しているだけです。

C:\Test\100_0011 (配列 arrName の 0 番目、つまり 1 つ目の項目)

_

8 (strMonth 変数の値)

_

3 (strDay 変数の値)

_

2007 (strYear 変数の値)

.

JPG (配列の 1 番目、つまり 2 つ目の項目)

これらの要素を組み合わせると、C:\Test\100_0011_8_3_2007.JPG になります。そうです。これは元のファイルのパスと写真の撮影日を組み合わせた名前です。

後は簡単です。ファイル名を変更するには、次のように FileSystemObject と MoveFile メソッドを使用します。

objFSO.MoveFile strName , strNewName

確かに、おかしな方法を使用してファイルの名前を変更しています。ここでは、Rename などのコマンドを使用せずに、ファイルを元のパス (C:\Test\100_0011.JPG) から新しいパス (C:\Test\100_0011_8_3_2007.JPG) に移動しています。最もわかりやすい方法ではありませんが、最終的にはファイルの名前が変更されているため、今回の目的は達成しています。

この後、MoveNext メソッドを呼び出して、レコードセット内の次のファイルに移動します。お決まりの台詞ですが、これで完成です。

完全な情報公開を期してお話しておくと、このコラムを執筆している Scripting Guy は毎朝欠かさず薬物検査を受けているわけではありません (検査を受けても、ステロイド、アンフェタミン、ヒト成長ホルモンなどの検査では陰性と診断されると思いますが、ドーナツやメープル バーの検査では陽性と診断されるでしょう)。信じられないかもしれませんが、Hey, Scripting Guy! のいくつかのコラムを読んだ後、皆さんはまず "このコラムの筆者はどんな薬物を使用しているんだろう" という感想を持つと思います。しかし安心してください。Hey, Scripting Guy! は薬物とは無縁です。よく言われることですが、勝者は薬物を使用しません。

そうですね、ツール ド フランスの勝者は使用したかもしれません。しかし、他の勝者は使用していませんし、このコラムを執筆した Scripting Guy も使用していません。


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