本連載ではここのところしばらく、PowerShellをインタラクティブシェルとして使うための設定やショートカットキーについて取り上げてきた。インタラクティブシェルとしてPowerShellを活用する基本的な方法は、網羅できたのではないかと思う。それを踏まえ、今回からはPowerShellをシェルスクリプトとして使っていく方法をまとめていこう。最終的には、PowerShellを使って日々の作業を自動化していくのが目標だ。

Hello World!

まずは、プログラミングの学習を始める際、”お約束”の「Hello World!」の出力をPowerShellのシェルスクリプトでやってみよう。何も考えず、最も簡単なコードだけを書いたファイルを作成する。ファイル名は「HelloWorld.ps1」にしておこう。

echo "Hello World!"

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

HelloWorld.ps1の実行サンプル

ここでのポイントは、PowerShellスクリプトの拡張子を「.ps1」にする点にある。Windowsでは拡張子が「.ps1」のファイルがPowerShellのシェルスクリプトファイルとして認識されるためだ。互換性を考えて、どのプラットフォームでもこの拡張子を使ったほうがよいだろう。

シェルスクリプトの引数「$args」

シェルスクリプトを使う場合、必要になる機能に引数の処理がある。シェルスクリプトに引数を指定して処理を変えたい場合があるからだ。PowerShellでは「$args」が自動的に生成される仕組みになっており、これをシェルスクリプトへの引数処理に使うことができる。その動きを知るための簡単なシェルスクリプトを作成してみよう。ファイル名は「HelloWorld2.ps1」としておく。

Write-Host("`$args: " + $args)
Write-Host("`$args.Length: " + $args.Length)
Write-Host("`$args[0]: " + $args[0])
Write-Host("`$args[1]: " + $args[1])
Write-Host("`$args[2]: " + $args[2])

Write-Host("Hello World!: " + $args[0])

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

HelloWorld2.ps1の実行サンプル

「argc」という変数名は、ほかのプログラミング言語でも引数を示す変数として使われることが多いので、これに関してはなじみのある方も多いだろう。

Linuxでも動くようにする

PowerShellはオープンソース化されて以降、WindowsのみならずLinuxやMacでも使うことができる。シェルスクリプトを作るのであれば、最初からLinuxやMacでも動くものを作ってしまおう。完全に互換性があるようにするには少しばかり気をつけなければいけないことがあるのだが、それはおいおい考えるとして、まずは基本的な書き方をまとめておこう。

まずHelloWorld2.ps1をLinuxで実行してみよう。互換性があるはずだが、次のように実行できない。

HelloWorld2.ps1はLinuxでは実行できない

これは、Linuxではシェルスクリプトとして「/bin/sh」が使われるのが前提となっているためだ。Linuxカーネルに、このシェルスクリプトがPowerShellのシェルスクリプトであることを教える必要がある。Linuxの場合、シェルスクリプトの先頭に「#!/usr/bin/pwsh」と書くことで実現できる。つまり、シェルスクリプトを次のように書き換えるのだ(/usr/bin/pwshはLinuxにインストールされるPowerShellの本体である)。

#!/usr/bin/pwsh

Write-Host("`$args: " + $args)
Write-Host("`$args.Length: " + $args.Length)
Write-Host("`$args[0]: " + $args[0])
Write-Host("`$args[1]: " + $args[1])
Write-Host("`$args[2]: " + $args[2])

Write-Host("Hello World!: " + $args[0])

ファイル名は「HelloWorld3.ps1」とした。Linuxカーネルは(Linuxカーネルに限らずUNIX系OSのカーネルは)、ファイルの最初が「#!」から始まっていた場合、その次に続く文字列を実行するという機能を備えている。つまり、ファイルの先頭に「#!/usr/bin/pwsh」と書いておくと、そのスクリプトの実行を「/bin/sh」ではなく「/usr/bin/pwsh」へ渡すようになる。Linux (ここではUbuntu 20.04)ではPowerShellは「/usr/bin/pwsh」にインストールされるので、つまりPowerShellで実行せよ、という意味になる。

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

LinuxでHelloWorld3.ps1を実行したサンプル

これをWindows 10で実行すると次のようになる。

Windows 10でHelloWorld3.ps1を実行したサンプル

PowerShellとしては「#」から始まる行はコメントだ。つまり、Windowsではファイルの先頭に「#!/usr/bin/pwsh」と書いても何の問題もない。これでWindows 10でもLinuxでも実行できるPowerShellシェルスクリプトの書き方の完成だ。

Macでも動くようにする

Linuxでも動くのだから、Macでも動くはずだ。HelloWorld3.ps1を実行すると次のようになる。

HelloWorld3.ps1

ご覧の通り、実行できない。これは、MacではPowerShellが「/usr/local/bin/pwsh」にインストールされるためだ。LinuxとほかのUNIX系OSではコマンドがインストールされるパスがしばしば異なっている。Linuxは「/usr/bin/」に突っ込む傾向が見られるが、Macや*BSD系は「/usr/local/bin/」に入れたり、それ以外のOSもサードパーティ製ソフトウエアのインストール先が異なっているケースが多い。つまり、ファイルの先頭に「#!/usr/bin/pwsh」と書くアプローチは、実行できるプラットフォームを限定してしまうことにつながる。

ではどうすればよいのか。よく使われるのは、次のようにファイルの先頭を「#!/usr/bin/env pwsh」と書く方法だ。

#!/usr/bin/env pwsh

Write-Host("`$args: " + $args)
Write-Host("`$args.Length: " + $args.Length)
Write-Host("`$args[0]: " + $args[0])
Write-Host("`$args[1]: " + $args[1])
Write-Host("`$args[2]: " + $args[2])

Write-Host("Hello World!: " + $args[0])

ファイル名は「HelloWorld4.ps1」とした。これは、Pythonスクリプトなどのマルチプラットフォームのスクリプトでよく使われるテクニックだ。Pythonもインストール先が「/usr/bin/python」だったり、「/usr/local/bin/python」だったりと異なることが多い。このため、ファイルの先頭に「#!/usr/bin/python」と書くと実行できないケースが出てくるのだ。

そこで、「/usr/bin/env」を使う。「/usr/bin/env」は、どの環境でも「/usr/bin/env」にあることが多い。envコマンドは環境変数を指定してその後に続くコマンドを実行するためのコマンドだが、環境変数を指定しなければ、ただ指定されたコマンドを実行するためのコマンドとして機能する。つまり、pythonを起動するためだけに使われることになる。これをpwshに対しても使えばよいというわけだ。

Macで実行してみよう。

HelloWorld4.ps1をMacで実行したサンプル

Linuxで実行すれば次のようになる。

HelloWorld4.ps1をLinuxで実行したサンプル

これでMacでもLinuxでも実行できるようになった。まずは、この書き方をPowerShellスクリプトの出発点としよう。せっかくマルチプラットフォームなシェルなのだ。どの環境でも使える(ようになる)状態で書き始めたほうがお得である。

PowerShellシェルスクリプトを書いていこう

シェルスクリプトに処理を書くようになると、さまざまなテクニックを書き留めておくことにもなるし、何かと重宝する。手動でやっている処理は、可能な限り自動化する。その要となるのはPowerShellだ。

WindowsではC#でかなりいろいろなことができるので、基本的にC#が使えればよいとは言え、かなりハードルが高いのも事実だ。C#と比べるとPowerShellのほうが非プログラマーにとってはとっつきやすいし扱いやすいと思う。PowerShellからC#の機能を使うこともできるので、(ちょっと書き方が難しくなるものの)PowerShellでかなりのことまでできるのだ。

今後は、PowerShellで実用的なスクリプトを作っていく方法に焦点を当てて解説していく予定だ。PowerShellを活用して、毎日の作業をより”楽”にしていこう。