前回のプログラム

前回はGet-FileInformationの枠組みを紹介しました。引き続き、forやswitchについて解説します。

1:$helpmessage = true   # ヘルプを表示するかどうかのフラグ
2:
3:for ($i = 0; $i -lt $args.length; $i++)
4:{
5:  switch($args[$i])
6:  {
7:      "today" {
8:          # 今日のファイル一覧を表示
9:          $helpmessage = false
10:     }
11:     default {
12:         # 何もしません
13:     }
14: }
15:}
16:
17:if ($helpmessage)
18:{
19: #ヘルプメッセージを表示
20:}

forによる繰り返し構文

3~15行では、forを使って、コマンドラインで指定されたパラメータを1つずつチェックする繰り返し構文です。

※ forによる繰り返し構文を、forループ(輪)と呼びます。

forは繰り返すたびに値が増える(あるいは減少する)変数を使って、同じ処理を繰り返すときに便利な構文です。使い方は以下の通りです。

for (初期値;  繰り返し条件; 値の増加または減少) { 繰り返す処理 }

今回のプログラムでは、変数iをインデックス(繰り返しを判定する値)として使います。最初に$i = 0でiの値を0に初期化します。

繰り返し条件は、{繰り返し処理}の部分を実行する条件です。$i -lt $args.lengthが成立するとき...つまりiの値がオプションパラメータの数未満の時に{繰り返し処理}(4~15行)を実行します。

$i++は、$i = $i + 1と同じで、iの値に1を加えます。

注意点は、$args.lenthの値(引数の数)が0のときは、最初から$i -lt $args.lengthの条件を満たさないので、繰り返し処理は「1度も」実行しません。また、iの値が$args.lengthに等しくなったとき、もはや繰り返し処理は実行しません。

switchによる条件処理

switchは、変数などの値を評価して、いくつかの処理に分岐する条件分岐構文です。条件分岐と言えば、基本はif構文。あらゆる条件分岐処理は、if構文を使って記述できます。しかし、あまりにもifが積み重なって複雑怪奇になっては見通しが悪いので、switchのようなパターン化された条件分岐構文も用意されています。

switchの構文は以下の通りです。

switch (評価される値)
{
    条件1 {条件1が成立したときに実行するプログラム}
    条件2 {条件2が成立したときに実行するプログラム}
     :
    条件x {条件xが成立したときに実行するプログラム}
    default {上記のどの条件も成立しなかったら実行するプログラム}
}

なお、defaultの処理が不要な場合でも、switch構文のブロック内には「default {}」を記述する必要があります。

たとえば、変数iの値が整数である場合、以下のようなプログラムを作成すると、iの値が1のとき「一」、2のとき[二]、3のとき「三」、それ以外の時「不明」を表示します。

switch ($i)
{
    1 { Write-Host "一"}
    2 { Write-Host "二"}
    3 { Write-Host "三"}
    default { Write-Host "不明"}
}

今回のプログラムでは、Get-FileInformationの実行時に指定されたコマンドラインパラメータforループで1つずつチェックします。そのforループの中で、コマンドラインパラメータ($args[$i])を順番にswitch構文で検証します。

$args[$i]の値が「today」のとき、今日のファイルを表示するための処理を行います(7~10行目)。それ以外の時、ヘルプを表示することにします(defaultの処理...11~13行目)。なお、既定の設定で、文字列評価で大文字小文字を区別しませんので、「today」、「Today」、「TODAY」すべて同じと見なします。

todayを評価するだけであれば、単純にifを使った方が簡単なのですが...、このプログラムは、今後、todayだけでなく、yesterday、lastweekなどにも対応しなければなりません。これからのプログラム拡張に備えて、多くのオプションに対応するためにswitch構文を使用します。

今日のファイルを表示

ここまでのプログラムを完成させます。今のところ、today以外のオプションパラメータは使用できません。

1:#ファイル情報一覧プログラム Ver.0.1
2:#オプション
3:# today
4:
5:#「今日」の開始時間と終了時間を算出
6:function TodayPeriod
7:{
8:  $date1 = Get-Date -Hour 0 -Minute 0 -Second 0
9:  $date1
10: $date1.AddDays(1)
11:}
12:
13:# $period  開始時間と終了時間を保持する配列変数
14:$helpmessage = $true # ヘルプを表示するかどうかのフラグ
15:
16:#オプションを確認
17:for ($i = 0; $i -lt $args.length; $i++)
18:{
19: switch($args[$i])
20: {
21:     "today" {       # 今日のファイル一覧を表示
22:         $helpmessage = $false
23:            $period = TodayPeriod
24:     }
25:     default {
26:         # 何もしません
    27:     }
28:     }
29:}
30:
31:#ヘルプを表示するか、ファイル一覧を実行
32:if ($helpmessage)
33:{
34:    Write-Output "Get-FileInformation Ver.0.1 - ファイル一覧コマンド"
35:    Write-Output ""
36:    Write-Output "使用方法"
37:    Write-Output "Get-FileInformation  <オプション>"
38:    Write-Output "オプション一覧"
39:    Write-Output "today    -    今日のファイルを表示。"
40:} else {
41:    Get-ChildItem -Recurse | `
42:    Where-Object `
43:    { ($_.LastWriteTime -ge $period[0]) -and ($_.LastWriteTime -lt $period[1]) }
44:}

※ 上記のプログラムに関しては、掲載当初、43行目の「$period[0]」と「$period[1]」を、それぞれ「$time[0]」「$time[1]」と表記しておりましたが、誤りでしたので修正させていただきました。ご迷惑をおかけした皆様に深くお詫び申し上げます。

Get-Information.ps1をそのまま実行、またはtoday以外のオプションパラメータで実行すると、ヘルプメッセージを表示します。

Get-Information.ps1に、todayオプションを指定して実行すると、本日作成または変更したファイルを一覧表示します。

テキストファイルに行番号を付ける

当連載でPowerShellのスクリプトプログラムに行番号を付けていますが、原稿執筆時に使っているのが、以下のスクリプトです。

 1:$lineno = 1
 2:foreach ($l in $input)
 3:{
 4: $lineno.ToString() + ":" + $l
 5: $lineno++
 6:}

1行目で行番号を1に初期化しています。

2行目のinputはパイプラインから入力されたオブジェクトを意味しており、foreach($l in $input)でinputから1行ずつ取り出してlに入れ、{}内の処理を繰り返します。全ての行を処理すると終了します。

4行目、linenoは数値オブジェクトなので、ToString()メンバ関数を使って文字列化してから、「:」や入力された行の値と結合します。

5行目でlinenoの値を1つ増加します。

このスクリプトプログラムをLineNo.ps1として保存すれば、以下のように実行して、Get-FileInfo.ps1のプログラムに行番号を付け、Get-FileInfo.txtに保存できます。

 Get-Content Get-FileInfo.ps1 | .\LineNo.ps1 > Get-FileInfo.txt

Get-Content(省略形gc)は、コンテンツ内容(テキストファイルの中身など)を出力するコマンドレットです。