Knowlbo 開発者ブログ

株式会社Knowlboの開発者ブログです。

PowerShell スクリプトで気をつけたい事

開発部の本橋です。 Windows でバッチ処理といえば cmd.exe ですが、cmd.exe で物足りない時に PowerShell を使う機会も増えてきました。PowerShell スクリプトを書く時に気をつけたい事をいくつか書いてみます。

推奨される Verb

PowerShell 標準のコマンドレットには 動詞-名詞 という命名規則があります。自分で function を作る時にもこの命名規則に従っておくと他の人が使う時にもわかりやすくていいです。

さらに、動詞(Verb)の部分には推奨される単語があります。Get-Verb コマンドレットで推奨される Verb を確認できます。

> Get-Verb

Verb Group
---- -----
Add Common
Clear Common
Close Common
Copy Common
Enter Common
Exit Common
...(略)

# 使いたい Verb を引数に取ることもできる。
> Get-Verb Save

Verb Group
---- -----
Save Data

動詞-名詞 の命名規則に従わなくても、さらには推奨される Verb を使わなくても別に良いのですが、ルールに則っておくと後々変な名前に悩まされることが少なくなります。

カレントディレクトリが2つある(ように見える)

pwd(Get-Locationコマンドレットのエイリアス)で取得できるカレントディレクトリと、 .NET 側の API である[System.IO.Directory]::GetCurrentDirectory()で取得できるカレントディレクトリが違います。

# カレントディレクトリは C:\Users\motohashi
> pwd

Path
----
C:\Users\motohashi

# .NET で用意されている API を使っても同じ
> [System.IO.Directory]::GetCurrentDirectory()
C:\Users\motohashi

# Cドライブの直下に移動するとカレントディレクトリは変わる
> cd C:\
> pwd

Path
----
C:\

# .NET で用意されている API を使うと変わっていない
> [System.IO.Directory]::GetCurrentDirectory()
C:\Users\motohashi

どうやらpwdは現在のセッションのカレントディレクトリを返し、[System.IO.Directory]::GetCurrentDirectory()は PowerShell プロセスのカレントディレクトリを返す、ということのようです。*1*2

これで何が困るかというと、.NET 側のクラスを使って相対パスでファイルを保存するようなケースです。

# 相対パスを指定してXMLファイルを読み込み
# pwd で取得できるディレクトリからの相対パスとなる。
$xmldoc = [xml](cat 'path/to/xml')

# ... xmlを変更 ...

# 相対パスを指定してXMLファイルを書き込み
# [System.IO.Directory]::GetCurrentDirectory() で取得できるディレクトリからの相対パスとなる。
$xmldoc.save('path/to/xml')

相対パスを使わずに絶対パスを使うようにするか、[System.IO.Directory]::SetCurrentDirectory()で PowerShell プロセスのカレントディレクトリを変更するようにするといいですね。