Hey, Scripting Guy!

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

Hey, Scripting Guy!

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

詳細情報

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

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

Hey, Scripting Guy! ダウンロード

Spacer

*

Windows PowerShell を使用して作成されてから 90 日以上経過したすべてのファイルをフォルダから削除する方法はありますか

Hey, Scripting Guy! Question

Scripting Guy さん、よろしくお願いします。Windows PowerShell で、2 つの日付の差分日数を特定する方法はありますか。作成されてから 90 日以上経過したすべてのファイルをフォルダから削除できるようにしたいのです。

-- JN

SpacerHey, Scripting Guy! AnswerScript Center

JN さん、こんにちは。今日は 10 月 31 日です。少なくとも米国では、暗黒の世界が世の中を支配する日です。魔女が意地悪そうに笑いながら通りを練り歩いたり、幽霊やゴブリンが前庭で跳ね回ったり、悪魔や悪霊がやってきて玄関の呼び鈴を鳴らしたりと、1 年のうちで悪によって支配される唯一の日です。つまり、・・・。いえいえ、編集者の誕生日ではありません (でも、そう考えると、いろいろ説明がつきますよね)。今日はハロウィンです。

: 再度確認しましたが、今日は編集者の誕生日ではありませんでした。彼女の誕生日は 7 月です。ですが、早めに手を打つことを好む方のためにお知らせしておくと、編集者がストックしているイモリの目とカエルの足指が残り少なくなり始めていますが、こうもりの毛と犬の舌はまだたくさんあるようです。

米国では、ハロウィン特徴は、子供たちが仮装して、人の家の呼び鈴を鳴らしお菓子を求めて回ることです (仮装は怖ければ怖いほど良いとされます)。3 回目になりますが、もう一度その日付を確認しましょう。今考えてみると、それはまさに編集者が去年の誕生日に行っていたことだとはっきりわかりました。

この祝日になじみのない方のために説明しておくと、ハロウィンのシンボル的な存在はかぼちゃのちょうちん (ジャック オ ランタン) です。これを作るには、かぼちゃをくりぬき、くりぬいたかぼちゃに顔を彫り、火をつけたろうそくを中に入れます。言い伝えによると、ジャック オ ランタンの起源は非常に古いそうです。ジャックという名前の酒好きのろくでなしが悪魔をだまして木に登らせ、悪魔が木の枝に腰掛けたところで、ジャックは、悪魔が木から降りられないように、木の幹に十字架を彫りました。そして、ジャックは、二度と自分に近づかないことを条件に、悪魔が木から降りられるようにしました。

数年後、ジャックは死んで天に召されましたが、生前の悪行が原因で天国に入ることを拒否されました。そして、地獄に送られることになりましたが、以前に悪魔をだましたことが原因で地獄にも入ることを拒否されました。結局、ジャックは永遠に地上をさまようしかありませんでしたが、悪魔は 1 つの慰めとして、暗闇の中を進めるように彼に火を灯したろうそくをあげました。

さて、4 回目になりますが、もう一度その日付を確認しましょう。この話は、編集者の履歴書からそのままコピーされたように見えるでしょうね。

とにかく、このイベントの精神に乗っ取って、このコラムを執筆している Scripting Guy は、今日のコラムで恐ろしくてぞっとするようなことをすることに決めました。作成されてから 90 日以上経過したすべてのファイルをフォルダから削除する Windows PowerShell スクリプトほど恐ろしくてぞっとするものはないと思います。

まあ、実際のところは、このスクリプトより恐ろしいことがほとんどですが。

$a = Get-ChildItem C:\Scripts 
foreach($x in $a) 
    { 
        $y = ((Get-Date) - $x.CreationTime).Days 
        if ($y -gt 90 -and $x.PsISContainer -ne $True) 
            {$x.Delete()} 
    }

このスクリプトのしくみを説明する前に、単純に 2 つの日付を減算する簡単な例を見てみましょう。このサンプル スクリプトは次のようになります。

$x = Get-Date 
$y = Get-Date "1/1/2007" 
$x - $y

ご覧のとおり、このスクリプトについては、それほど複雑なことはありません。1 行目では、Get-Date コマンドレットを使用し、現在の日時を取得して $x という名前の変数に格納しています。2 行目では、Get-Date コマンドレットを使用して、2007 年 1 月 1 日に相当する日時値を取得しています。この 2 つ目の値を取得する際に時刻を指定しなかったため、日時のインスタンスには、既定の時刻である午前 12 時が指定されることに注意してください。では、特定の時刻を指定した場合はどうなるのか、ですって。問題ありません。ナイキの優秀な社員が言っているように、とにかくやってみてください (JUST DO IT)。

$y = Get-Date "1/1/2007 9:45 PM"

さて、$x と $y という 2 つの日時値を用意できたら、次はどうするのかというと、この 2 つの日付の差分時間を特定するために一方の値からもう一方の値を引くだけです。$x から $y を引いて、返される結果を確認してください。

Days              : 302 
Hours             : 9 
Minutes           : 27 
Seconds           : 47 
Milliseconds      : 515 
Ticks             : 261268675156250 
TotalDays         : 302.394299949363 
TotalHours        : 7257.46319878472 
TotalMinutes      : 435447.791927083 
TotalSeconds      : 26126867.515625 
TotalMilliseconds : 26126867515.625

一覧の先頭に、必要な値があります。つまり、現在の日付 (このコラムが執筆された 2007 年 10 月 30 日) と 2007 年 1 月 1 日の間には 302 日の差があることがわかりました。悪くないですね。

はい、ご指摘のとおりです。悪くはありませんが、それほど良いというわけでもありません。というのも、ここでは必要のない、無関係なプロパティ値 (Hours、Minutes、Second、Milliseconds など) が多数含まれているからです。でも、大丈夫です。スクリプトの最後の行を次のように変更して、結果を確認してみましょう。

($x - $y).Days

ここで行っている処理をご説明しましょう。$x から $y を引いている点は同じですが、ここでは、この簡単な日付の計算をかっこ内で実行している点が異なります。というのも、ここでは、2 つの処理を実行する必要があるからです。まず、一方の日付値をもう一方の日付値から引く必要があります ($x - $y)。この処理によって、.NET Framework の System.TimeSpan クラスのインスタンスが返されます。

もう 1 つの処理は、その TimeSpan オブジェクトの Days プロパティの値を表示することです。TimeSpan オブジェクトを取得してから Days プロパティの値を取得するように、この簡単な数式をかっこで囲んでいます。PowerShell では、常に、かっこ内のコマンドが他の処理よりも先に実行されます。したがって、まず日付の計算を実行し、TimeSpan オブジェクトが返されたら、かっこ外の処理に移って Days プロパティの値を取得します。

これは本当にうまくいくのか、ですって。ご自分で確かめてください。

302

これでようやく、作成してから 90 日以上経過したすべてのファイルをフォルダから削除するスクリプトについて説明する準備ができました。このスクリプトでは、まず Get-ChildItem コマンドレットを使用して C:\Scripts フォルダ内のすべてのオブジェクトのコレクションを取得します。このコレクションは $a という名前の変数に格納されます。

$a = Get-ChildItem C:\Scripts

: 何ですって。このタスクを C:\Scripts のサブフォルダにあるすべてのファイルに対して実行したい方もいらっしゃるのですか。お任せください。その場合は、Get-ChildItem コマンドに –recurse パラメータを追加すればうまく行きます。

$a = Get-ChildItem C:\Scripts -recurse

次は、コレクション内のすべてのアイテムをループ処理する foreach ループを設定します。このループ内での最初の処理として、次のコード行を実行します。

$y = ((Get-Date) - $x.CreationTime).Days

最初にこのスクリプトをお見せしたときに、皆さんはこのコード行を見て「大変だ・・・」と言ったかもしれません。でも、この時点では、ここで行っている処理を正確に理解できると思います。

では、ここでは何をしているのかというと、まず、Get-Date コマンドレットを使用して、現在の日時を取得しています (Get-Date コマンドレットが入れ子になったかっこ内にあることに注意してください。これにより、他の処理を実行する前に、現在の日時が取得されます)。現在の日時を取得したら、最初のアイテムの CreationTime プロパティの値を取得し、Get-Date コマンドレットで取得した値からその値を引きます。ご存知のとおり、この式では TimeSpan オブジェクトが返されます。このオブジェクトが返されたら、Days プロパティの値を取得して、その値を $y という名前の変数に格納します。

そして皆さんのおっしゃるとおり、見た目は複雑ですが、実際は非常に簡単です。

では、次の行に移りましょう。

if ($y -gt 90 -and $x.PsISContainer -ne $True)

ここで行われる処理は 2 つあります。まず、$y 変数の値から、現在の日時と、コレクション内の最初のアイテムが作成された日時の間の差分日数がわかります。ここでは、この値が 90 より大きいかどうかを確認し (-gt)、大きい場合は、このアイテムが削除対象の候補になります。

なぜ削除対象の "候補" なのか、ですって。必要なのはファイルの削除だけであり、フォルダは削除しないからです。そこで、次の簡単なコードを使用します。

$x.PsISContainer -ne $True

ここでは、PsISContainer プロパティの値が (PowerShell 組み込み変数 $True で表される) True と等しいかどうかを確認している (-ne) だけです。PsISContainer プロパティの値が True の場合、処理対象がフォルダなので、フォルダの操作 (つまり、削除) は必要ありません。PsISContainer プロパティの値が False の場合は問題ありません。つまり、その場合は、処理対象がファイルであるということです。

たとえば、作成してから 90 日以上経過しているファイルがあるとします。その場合に必要な作業は、Delete メソッドを呼び出して当該ファイルを削除するだけです。

{$x.Delete()}

その後、ループの先頭に戻り、コレクション内の次のアイテムに対して同じ処理を繰り返します。

確かに、このスクリプトはもう少し簡単なものにできたかもしれません (やっぱり、できないかもしれません。これは、何よりもセンスが良いと評価されています)。ですが、この方法を使用したので、一石二鳥になりました。PowerShell の日付計算の基本を説明して、さらにはフォルダ内にある古いファイルすべてを削除することができました。1 つ分の報酬で 2 つのことをやってのけたことを、スクリプトの世界に向けたハロウィンの贈り物と考えていただければさいわいです。

: 実際には、一石二鳥ではありませんでした。これは、うまく扮装したスタント マンとコンピュータ アニメーションを組み合わせた特殊効果によって行われました。

これでご質問の回答になっているとよいのですが、JN さん。このコラムを執筆している Scripting Guy は、本当はハロウィンが好きではないのですが、家に帰って、ハロウィンでお菓子をもらいに来る子供たちにキャンデーをあげる予定です。それは彼が悪魔や悪霊に抵抗するためなのか、ですって。いいえ、とんでもありません。彼がマイクロソフトで働いているのをお忘れですか。ハロウィンは、以前は子供たち限定の祝日でしたが、現在、多くの大人たちもその祝日を採り入れています。実際、多くの親は、自分の子供がハロウィンのお菓子をもらいに行くことを許可すらしていません。というのも、親たちは子供が毒入りのキャンデーをもらってくることを恐れているからです (ですが、子供たちがハロウィンにお菓子をもらいに行って毒入りのキャンデーをもらってきたと報告されている事件はありません)。

代わりに、親はベビーシッターを雇い、子供たちを家において、自分たちが仮装してパーティに参加します。このコラムを執筆している Scripting Guy は、このような親の行為は子供たちに対してひどいことだと思っています。そういうわけで、彼はハロウィンが好きではないのです。

Scripting Guy とは対照的に、編集者はハロウィンが大好きです。彼女は、一年のうちで、"自分らしくなれる" 唯一の日だと言っています。さて、最後にもう一度だけ、その日付を確認しておきましょう…。

編集者注 : 事実を明らかにするために一言付け加えますが、編集者の誕生日は 10 月 31 日ではありません。仮にそうだったとしても、何も否定的な意味はありません。世の中には、ハロウィンに生まれた、いたって普通の人が大勢います。編集者がハロウィンをどのように過ごすかというと、スクリプト犬に手伝ってもらいながら、親にお菓子をもらいに行くことを許可されているすべての子供たちにキャンデーを配ります (5 年ほど前のある年には、100 人を上回る子供にキャンディーを配りました)。


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