自作のコマンドレットを作る

Windows PowerShellでは、.Net FrameworkとC#などの開発環境を用いて本格的なコマンドレットを開発できますが、もっと手軽なコマンドレットの作成方法として、関数(function)とスクリプトファイルがあります。汎用性の高い処理、頻繁に実行する定型処理などは、自作コマンドレットにするといいでしょう。今回は、まず関数から紹介します。

関数の定義

PowerShellによる一連の処理(プログラム)に名前をつけて、コマンドレットのように使えるようにするのが関数です。基本的な定義書式は以下のようになります。

function  関数名 {
    (処理)
    return  返値
}

記述するとき必ずしも改行したりインデント(字下げ)をつける必要はありませんが、こうしたスタイルで記述した方がプログラムの構造を見やすく、プログラミングミスを防止できます。もっとも、数ワード以下で記述できるような短い内容の関数では、改行せずに以下のように1行にまとめた方が簡潔で明瞭な場合もあります。

function  関数名 {(処理); return 返値 }

PowerShellの場合、1文の末尾にはセミコロン「;」を使用します。1行に複数の文を記述する場合には「;」で区切らなければなりません。一方、文の末尾が改行の場合、文が完全な状態であれば改行も「;」と同様に文末記号として扱います。しかし、文が不完全であれば、改行を空白と同じ単なる単語区切りとして扱い、次の行に続きます。

returnはプログラムの終了点を意味します。関数の途中にreturnがあれば、そこで処理を終了します。また関数の処理結果を、この関数を呼び出したプログラム(PowerShellまたは他の関数)に返すときは、返値(かえりち)を指定します。返値不要で終了点も明示する必要がない場合は、returnを省略できます。

関数に入力値が必要なときは、配列型の自動変数$argsを使用します。関数に入力するための変数を引数(ひきすう)と呼び、最初の引数は$args[0]、2番目の引数は$args[1]...というようにインデックス番号をつけて参照します。PowerShellコマンドプロンプトで関数を実行するとき、プロンプトに記述したパラメータが引数となります。バッチコマンドの%1、%2、%3...に相当すると考えるといいでしょう。

※ 配列とは、同じ名前の変数をセットにして、インデックス番号で区別しながら扱う手法です。

※ PowerShell関数では、他にパイプラインからの入力を使用するための自動変数$inputもあります。また、引数の数や型を固定したいときは、自動変数$argsを使用するのではなく、function name ([int]$num1, [string]$mes )のように指定して引数名と型を明記することもできます。今後の記事で紹介します。

単純な関数

関数の働きを見るために、実際に単純な関数を作成しましょう。関数に渡した2つのパラメータを足し算して表示する関数、testを作成します。

function  test
{
    $args[0] + $arg[1]
}

testという名前の関数を定義。

1行目を入力した後にプロンプトが「>>」に代わりますが、これは前行の続きであることを意味します。プログラムの最後の行を入力した後、もう一度Enterキーを押すと、プロンプトに戻ります。

この程度の短い関数であれば、以下のように1行で記述してもかまいません。

function  test { $args[0] + $args[1]  }

testを実行してみましょう。

testの実行。通常のコマンドレットのように実行できます。

※ PowerShellでは、代入先がない式で変数や文字列を記述すると、式の値を表示します。メッセージ表示のために、明示的に表示するためのステートメントや関数を記述する必要はありません。

追記 : 今回の記事のプログラムで「表示」として説明した出力は、厳密に言えばパイプライン出力であり、関数の返値です。リダイレクトしなければ画面に表示しますが、厳密な意味で"表示"するためにはWrite-Hostコマンドレットなどを使います。パイプラインと表示の使い分けについては、パイプライン入力と合わせて後の機会に説明したいと思います。

引数の数

引数の数は$argsのプロパティ、countで知ることができます。たとえば、引数が2つ未満のとき、エラーメッセージを表示するには、以下のようにプログラムを組みます。

function test
{
    if ($args.count -ge 2 ) {
        $args[0] + $args[1]
    } else {
        "2つのパラメータを指定して下さい"
    }
}

引数の数($args.count)が、2以上(-ge)であれば、2つの引数の和を計算して表示し、そうでなければメッセージを表示します。

※ PowerShellプロンプトで日本語入力をするとき、[半角/全角]キーを押しても仮名漢字変換を使用できない環境では、[Alt] + [半角/全角]キーを押して下さい。

関数の定義と実行結果。testのパラメータが2つ未満のときは、エラーメッセージを表示します。

※ すでに作成した関数と同じ関数名で定義すると、PowerShellは既存の関数を破棄して、新しい内容に関数を書き換えます。

テキストファイルをコピーする関数の作成

少し実用的な関数を作成してみましょう。何度もカレントディレクトリのテキストファイル(拡張子.txt)をコピーしなければならないとします。毎回拡張子.txtを指定するのは面倒ですので、テキストファイルだけをコピーする関数、Copy-Textfileを作ってみましょう。PowerShellのプロンプトで以下のプログラムを入力してください。

function  Copy-Textfile
{
    if ($args.count -eq 1 ) {
        Copy-Item  ./*.txt  $args[0]
        "コピー終了しました。"
    } else {
            "テキストファイルのコピー先ディレクトリを指定して下さい。"
    }
}

パラメータがないか、2つ以上なら、エラーメッセージを表示します。パラメータが1つなら、それをコピー先ディレクトリとしてCopy-Itemコマンドレットでコピーします。

関数の修正と確認と削除

関数一覧を表示するには、Get-ChildItemコマンドレットでfunction:プロバイダを指定します。

あらかじめ組み込まれている関数も一緒に表示。

また、特定の関数の有無を確認するには、ファイル一覧を表示させるときのように、関数名を指定します。ワイルドカードも使用できます。

ワイルドカードを指定してtestで始まる関数だけを表示。

関数を修正するには、同じ関数名で再定義します。残念ながら、部分的に修正することはできません。

作成した関数を削除するときは、Remove-Itemコマンドレットを使います。

「Remove-Item funciton:関数名」で、関数を削除。

関数の寿命(有効範囲)

こうして設定した関数は、残念ながら、PowerShellを終了すると破棄されます。次回PowerShellを起動したときにはもはや使用できません。PowerShellを終了すれば消えてしまうのですから、気軽に関数を作成しても、むやみに関数が増えて混乱する心配はありません。

作成した関数を継続的に使用したい場合には、スクリプトを作成します。次回はスクリプトの作成と実行について紹介します。