マイナビニュースマイナビ

PowerShell 7をシェルスクリプトとして使う - パラメータを使う

【連載】

PowerShell Core入門 - 基本コマンドの使い方

【第148回】PowerShell 7をシェルスクリプトとして使う - パラメータを使う

[2021/05/14 08:00]後藤大地 ブックマーク ブックマーク

今回はこれまで作ってきたスクリプトを、PowerShellの提供機能を使ってPowerShell風に整理していく。無理やりUNIX系のシェルスクリプトのように書くこともできるが、まずはその言語が提供している機能で書いておくほうが無難だ。今回は、引数としてパラメータを使う場合の処理を書いていく。

前回作ったスクリプトの”問題”

前回作ったスクリプト(test-d_9.ps1)は次の通りだ。

#!/usr/bin/env pwsh

# 1つの引数が必要。引数はディレクトリパス。
if (0 -eq $args.Length) {
    Write-Error "usage: test-d_2.ps1 ディレクトリパス"
    exit 1
}

if (Test-Path -PathType Container -Path $args[0]) {
    # 指定されたパスはディレクトリ
    $True
} else {
    # 指定されたパスはディレクトリではない
    if (Test-Path -PathType Leaf -Path $args[0]) {
        # 指定されたパスはファイル
        Write-Host "$args[0]: ファイルです。"
    } else {
        # 指定されたパスは存在しない
        Write-Host "$args[0]: そのようなディレクトリは存在しません。"
    }
    $False
}

実行すると次のようになる。

実行サンプル

いくつか問題があるのだが、まずはusageの出力に注目してみよう。スクリプトの名前が「test-d_2.ps1」になっている。実際には「test-d_9.ps1」だ。これはスクリプト名をハードコーディングしてあるため、この部分の書き換えを忘れたことで発生したバグということになる。

まずはこういった細かい部分を書き換えていく。

スクリプト名を取り出して利用する

スクリプトパスが「$PSCommandPath」という変数に収められている。これを使ってusageを出力するように変更したのが次の「test-d_10.ps1」だ。

#!/usr/bin/env pwsh

$scriptname = $PSCommandPath

# 1つの引数が必要。引数はディレクトリパス。
if (0 -eq $args.Length) {
    Write-Error "usage: $scriptname ディレクトリパス"
    exit 1
}

if (Test-Path -PathType Container -Path $args[0]) {
    # 指定されたパスはディレクトリ
    $True
} else {
    # 指定されたパスはディレクトリではない
    if (Test-Path -PathType Leaf -Path $args[0]) {
        # 指定されたパスはファイル
        Write-Host "$args[0]: ファイルです。"
    } else {
        # 指定されたパスは存在しない
        Write-Host "$args[0]: そのようなディレクトリは存在しません。"
    }
    $False
}

実行すると次のようになる。

実行サンプル

スクリプト名が絶対パスで表示されていることがわかる。これでは使いにくいので、スクリプトパスからスクリプト名だけ取り出して使うように、次のように書き換える(test-d_11.ps1)。

#!/usr/bin/env pwsh

$scriptname = Split-Path -Leaf $PSCommandPath

# 1つの引数が必要。引数はディレクトリパス。
if (0 -eq $args.Length) {
    Write-Error "usage: $scriptname ディレクトリパス"
    exit 1
}

if (Test-Path -PathType Container -Path $args[0]) {
    # 指定されたパスはディレクトリ
    $True
} else {
    # 指定されたパスはディレクトリではない
    if (Test-Path -PathType Leaf -Path $args[0]) {
        # 指定されたパスはファイル
        Write-Host "$args[0]: ファイルです。"
    } else {
        # 指定されたパスは存在しない
        Write-Host "$args[0]: そのようなディレクトリは存在しません。"
    }
    $False
}

実行すると次のようになる。

実行サンプル

usageに使われるスクリプト名が適切に出力されるようになったことがわかる。

こういった書き換えは結構重要だ。なぜかと言うと、結局こういうコードはコピー&ペーストで使い回すことが多いので、名前などがハードコーディングされていると書き換えられず使われてしまうケースが多いからだ。上記のように、コピー&ペーストしてもうまく機能するようにしておけば、将来の自分が楽になる。

パラメータを使えるようにする

さて、今回の主題はパラメータだ。このスクリプトでパラメータを指定できるようにしたい。PowerShellでは「Param()」がパラメータの処理を行うために使われるので、これを使ってスクリプトを書き換える。まずは、usageを表示する処理を明示的にパラメータで実行できるようにする。「-Help」でusageが出力されるようにしてみよう。書き換えたスクリプト(test-d_12.ps1)は次の通りだ。

#!/usr/bin/env pwsh

#====================================================================
# 引数処理
#====================================================================
Param(
    [switch]$Help
)

if ($Help -Or (0 -eq $args.Length)) {
    $scriptname = Split-Path -Leaf $PSCommandPath
    Write-Error "usage: $scriptname [-Help]"
    exit 1
}

#====================================================================
# ディレクトリパスの存在確認処理
#====================================================================
if (Test-Path -PathType Container -Path $args[0]) {
    # 指定されたパスはディレクトリ
    $True
} else {
    # 指定されたパスはディレクトリではない
    if (Test-Path -PathType Leaf -Path $args[0]) {
        # 指定されたパスはファイル
        Write-Host "$args[0]: "`
            + "ファイルです。"
    } else {
        # 指定されたパスは存在しない
        Write-Host "$args[0]: "`
            + "そのようなディレクトリは存在しません。"
    }
    $False
}

実行すると次のようになる。

実行サンプル

「-Help」でusageが出力されていることを確認できる。

パラメータの処理を自前で行うこともできるが、「Param()」を使うと、PowerShellの「Tab」キーによる補完機能が使用できるようになる。例えば、今回の例であれば「-」と入力した段階で「Tab」キーを押すと、「-Help」まで入力が補完される。そのほか便利な機能も自動的に動き出すので、PowerShellの流儀に従って書いておくと何かと便利なのである。

さらにパラメータを使う

さらにもう少しパラメータを使うように書き換えてみよう。これまではディレクトリパスを引数として指定していたが、これをパラメータで指定できるようにする。-DirectoryPathでディレクトリパスを指定できるようにしよう。指定順序も考慮すると、次のように書いておけば、-DirectoryPathパラメータを指定しても、これまでのようにディレクトリパスだけを指定しても実行できるようになる(test-d_13.ps1)。

#!/usr/bin/env pwsh

#====================================================================
# 引数処理
#====================================================================
Param(
    [string]$DirectoryPath,
    [switch]$Help
)

if ($Help -Or -Not $DirectoryPath) {
    $scriptname = Split-Path -Leaf $PSCommandPath
    $errmsg = "usage: $scriptname " `
        + "[-DirectoryPath] ディレクトリパス " `
        + "[-Help]"
    Write-Error $errmsg
    exit 1
}

#====================================================================
# ディレクトリパスの存在確認処理
#====================================================================
if (Test-Path -PathType Container -Path $DirectoryPath) {
    # 指定されたパスはディレクトリであり、存在している。
    $True
} else {
    # 指定されたパスはディレクトリではない。
    if (Test-Path -PathType Leaf -Path $DirectoryPath) {
        # 指定されたパスはファイル。
        $infomsg = "$DirectoryPath : " `
            + "ファイルです。"
    } else {
        # 指定されたパスは存在しない。
        $infomsg = "$DirectoryPath : " `
            + "そのようなディレクトリは存在しません。"
    }
    Write-Host $infomsg
    $False
}

実行すると次のようになる。

実行サンプル

かなりPowerShellらしい動作をするようになってきた。「Tab」キーによる補完機能は動作するし、パラメータ指定と順位による指定が機能している。

このように、PowerShellのスクリプトにはある程度決まったパターンがある。この書き方を最初に覚えてしまえば、ある程度体裁の整ったスクリプトを作ることができる。最初は小さい機能を作るところから、スクリプトの書き方を覚えていくとよいだろう。

※ 本記事は掲載時点の情報であり、最新のものとは異なる場合がございます。予めご了承ください。

一覧はこちら

連載目次

もっと知りたい!こちらもオススメ

【連載】RPA入門 - ツールで学ぶ活用シーン

【連載】RPA入門 - ツールで学ぶ活用シーン

AIには、ルールベース、機械学習、深層学習(ディープラーニング)の3つのレベルがあり、レベルが上がるに連れてより高度な人工知能を実現しますが、AIのスピンオフという位置付けで、Digital Labor(仮想知的労働者)によるホワイトカラー業務の自動化を実現するRPAが注目されています。

関連リンク

この記事に興味を持ったら"いいね!"を Click
Facebook で TECH+ の人気記事をお届けします
注目の特集/連載
[解説動画] Googleアナリティクス分析&活用講座 - Webサイト改善の正しい考え方
Slackで始める新しいオフィス様式
Google Workspaceをビジネスで活用する
ニューノーマル時代のオウンドメディア戦略
ミッションステートメント
次世代YouTubeクリエイターの成長戦略
教えてカナコさん! これならわかるAI入門
AWSではじめる機械学習 ~サービスを知り、実装を学ぶ~
Kubernetes入門
SAFeでつくる「DXに強い組織」~企業の課題を解決する13のアプローチ~
AWSで作るマイクロサービス
マイナビニュース スペシャルセミナー 講演レポート/当日講演資料 まとめ
セキュリティアワード特設ページ

一覧はこちら

今注目のIT用語の意味を事典でチェック!

一覧はこちら

会員登録(無料)

ページの先頭に戻る