PowerShell上での使い方の調べ方

業務ではアプリ開発やコンテナ利用のためLinuxでbashを使っているのですが、自宅のWindowsでも一部シェルで作業したくなり、せっかくなのでPowerShellを使ってみることにしました。

Linuxでは、コマンドに `-h` オプションを付けたり `man` コマンドを使うことで、その場でコマンドの使い方を調べられます。PowerShellでも**その場で使い方がわかると楽**だと思い、まずは調べ方を探ることにしました。実際に試行錯誤してわかった「調べ方」をまとめます。

- コマンドの検索
- ヘルプの閲覧
- 変数の確認
- オブジェクトの調査
- 型の調査

---

記載したコマンドは、以下の環境で動作確認しています。

| PowerShellバージョン | OS |
|:-:|:-:|
| 5.1.19041.610 | Windows 10 |
| 7.0.3 | Ubuntu 18.04<br>（[Dockerコンテナ](https://hub.docker.com/_/microsoft-powershell)） |

## 調べるためのコマンドまとめ
### コマンドの検索
PowerShellのコマンド（特にコマンドレット）は命名が `<動詞>-<名詞>` と統一的なので、名前を見れば機能の見当がつきます。なので、コマンド一覧を出せれば困ったときの手掛かりになります。

```powershell:コマンドを名前で検索
Get-Command Get-*
```

```powershell:動詞（Verb）や名詞（Noun）で検索
Get-Command -V *move* -No *item*
```

```powershell:コマンド種別で絞り込み
Get-Command -C Application  # パスの通っている実行可能ファイル
```

```powershell:エイリアス正引き
Get-Command g* -C Alias
Get-Alias g*
```

```powershell:エイリアス逆引き
Get-Alias -D Get-*
```

ちなみにbashのように `alias` と打っても動作しますが、これはコマンドとしては存在しません。PowerShellは「見つからなかったコマンドは `Get-` を付けてリトライする」らしいです。

- [What runs in PowerShell when I type &quot;alias&quot;? - Stack Overflow](https://stackoverflow.com/questions/2128844)

### ヘルプの閲覧
使えそうなコマンドが見つかったら、使い方の詳細はヘルプを見ればいいです。パラメータ、入出力の型、使用例など様々な情報があります。

また、各コマンドの使い方だけでなく、PowerShellの基礎について説明したものもあります。

※ コンピュータにヘルプファイルが入っていない場合は十分な情報を得られません。管理者権限で `Update-Help` コマンドを実行しておく必要があります。

```powershell:コマンドのオプションから（&#x20;<code>-h</code>&#x20;相当）
Get-Location -?
```

```powershell:ヘルプコマンドから、全ての内容を表示
Get-Help Get-Location -Full | more  # Linuxなら `less` も可
help Get-Location  # help は内容を自動的にページング
```

※ Windows PowerShell 5.1 では、 `help` コマンドでも `-Full` を付ける必要がありました。

```powershell:ヘルプを検索
help *operator*
```

```powershell:ヘルプのカテゴリで絞り込み
help *output* -Ca HelpFile
```

### 変数の確認
変数はユーザ自身で定義できるほか、あらかじめ用意されているものもあります。

変数は先頭に `$` を付けて使うのが簡単です。また、 `Variable:` や `Env:` といった特殊なドライブ[^psdrive]を用いると、ファイルのように扱うこともできます。

```powershell:変数の一覧
Get-Variable
Get-Item Variable:*
```

```powershell:環境変数の一覧
Get-Item Env:*
```

```powershell:変数の取得
$PSVersionTable
Get-Content Variable:PSVersionTable
```

```powershell:環境変数の取得
$env:PATH  # Linuxでは環境変数の大文字・小文字が区別される
Get-Content Env:PATH
```

[^psdrive]: ドライブの一覧は `Get-PSDrive` で確認できます。

### オブジェクトの調査
PowerShellの特徴は、パイプや引数において**文字列でなくオブジェクト**で渡していることです。逆に言えば活用するためには、そのオブジェクトが何であるか、どんなメソッドやプロパティがあるか、などを把握する必要があります。

```powershell:オブジェクトの型やメソッドなど全般
$obj = Get-ChildItem
$obj | Get-Member   # 配列の場合は要素の種類毎
Get-Member -I $obj  # 配列の場合は配列そのもの
```

```powershell:オブジェクトの型を取得
$obj = Get-ChildItem
$obj.GetType()
$obj[0].GetType()
```

```powershell:メソッドの多重定義を一覧化
$obj = Get-Item ~
$obj.GetFiles  # 括弧を付けずにメソッドを呼ぶ
```

#### 応用：コマンドの情報
最初の `Get-Command` は**コマンド情報のオブジェクト**を返すので、それを利用するとヘルプを表示せず一部の情報を抜き出せます。

```powershell:コマンドレット
$cmdlet = Get-Command Get-Item
$cmdlet.Definition  # パラメータの構文
$cmdlet.OutputType  # 出力としてあり得る型（ヘルプと違う？）
$cmdlet.Parameters
```

```powershell:エイリアス
$alias = Get-Command gi
$alias.Definition                  # エイリアスだと構文を見れない
$alias.ResolvedCommand.Definition  # 元のコマンドなら構文を見れる
```

```powershell:関数
$func = Get-Command help
$func.Definition  # 関数定義（＝スクリプト）を見れる
$func.Parameters
```

### 型の調査
オブジェクトがすぐ手に入らないときは、型から直接情報を得る方法があります。

```powershell:型に使えるメソッドなど（前節と同じ）、名前で絞り込み
[regex] | Get-Member Get*s
```

```powershell:メソッドなど全般
# リスト形式だと長いので、 Format-Table コマンドで表形式にしてプロパティも絞る
[regex].GetMembers() | ft Name, MemberType, ReturnType, Attributes
```

```powershell:メソッド（絞り込み）
# 単純に Where-Object コマンドで条件指定する
[regex].GetMethods() | ? { ! $_.IsStatic } | ft Name, ReturnType, Attributes
```

## 調べてみて
じっくりヘルプを読むだけならインターネットのほうが良さそうですが、今回は調べるために手を動かし試行錯誤したことで、**PowerShellの基本的な操作に慣れる**ことができました。慣れてくると「こんなこともできるのでは？」と見当をつけられ、できることがどんどん増えていくのがその場でわかって楽しかったです。

PowerShellをbashの代替として見ていた頃は、文法が飲み込めず自力でスクリプトを組み立てることができませんでした。しかし、以下の2点に気付いたときから一気に見方が変わり、文法を理解できるようになりました。

- コマンドの結果は普通に変数に代入できる、逆に変数部をコマンドに置換もできる[^paren]
- 「コマンドの結果」でなく「単なるオブジェクト」をパイプで送り込める

コマンドをパイプで繋いでいるのは、一般的なオブジェクト指向プログラミングでメソッドを繋げるのと同じように見えます。メソッドの引数に丸括弧を使わなくていい言語はRubyなどいろいろあるので、それらから類推すれば文法は不思議には感じなくなりました。配列リテラルに括弧がいらないのは驚きましたが、コマンドのパラメータに渡す[^array]ことを考えれば納得しました。

[^paren]: 変数部をコマンドに置換する際は、基本的に丸括弧で囲む必要があります。
[^array]: 今回は `Format-Table` コマンドで使っています。

---

そんなわけで、当初の「Windowsでも一部シェルで作業」ができるようになり、GUIでは面倒だった単純作業などを少しずつ改善しています。~~WSLで済ませているものも多いですが。~~

## 参考

- 今回参照したもの
	- **PowerShellのヘルプ**（ `Get-Help` コマンド）
	- [Docker での PowerShell の使用 - PowerShell | Microsoft Docs](https://docs.microsoft.com/ja-jp/powershell/scripting/install/powershell-in-docker)
- オンラインで調べるのに役立ちそうなもの
	- [PowerShell 101 - PowerShell | Microsoft Docs](https://docs.microsoft.com/ja-jp/powershell/scripting/learn/ps101/00-introduction)
	- [PowerShell モジュール ブラウザー - PowerShell | Microsoft Docs](https://docs.microsoft.com/ja-jp/powershell/module/?view=powershell-7)
	- [.NET API ブラウザー | Microsoft Docs](https://docs.microsoft.com/ja-jp/dotnet/api/?view=powershellsdk-7.0.0)