Select-StringのPathのワイルドカードがわからないけどどうにかなって頭がどうかなりそうな件

## この記事が言いたいことを三行でまとめて

1. Select-StringのPathパラメータはワイルドカードが使えるが正規表現は使えない
1. しかしPathパラメータにはString配列を使って指定できる複数のPath（実質的なOR表現）を実現できる
1. やりたいことができたけどMicrosoftの設計思想に納得がいかなくてついつい書きなぐる

## Select-Stringの-Pathパラメータに正規表現を使用したい人生だった

さて、以下のようなフォルダー構成とする。よくある日付フォルダーにログファイルが入っているという構成だ。

    C:\work\
    +-20200801
      + abc.log
    +-20200802
      + abc.log
    +-20200803
      + abc.log
    ...
    +-20200813
      + abc.log
    +-20200814
      + abc.log
    +-20200815
      + abc.log
    ...
    +-20200830
      + abc.log
    +-20200831
      + abc.log

これに対して、そもそも下のようなコマンドが使えていた。

```PowerShell
PS C:\Work> Select-String -Path ./2020080[1-5]/abc.log -Pattern "Hoge"
C:\work\20200802\abc.log:3 Hoge
C:\work\20200805\abc.log:3 Hoge
```

というふうに\[1-5\]という表現を使えるので、すっかり正規表現を使えるものだと思い込んでいた。

で、やりたいことは1日から15日といったもっと長い期間の指定をしたかった。だが、そのためには\[\]では足りない。

先日に書いた[https://qiita.com/gat3ta/items/11bff27c7a1d1d315fbc 正規表現の記事]もそれをしたくて考えていた記事のわけだ。

そして、正規表現のOR表現に行き着く。

満を持して、下のコマンドを打ったところ、なんと！

```PowerShell
PS C:\Work> Select-String -Path ./202008(0[1-9]|1[1-5])/abc.log -Pattern "Hoge"
PS C:\Work>
```

ううん。もともとあった方の結果も出ないぞ？

違うコマンドを打ってみて、どうやら何かが悪いようだ。ということで、調べた結果からカッコと|（or表現）は使えないということは突き止めた。少しばかり考えてみる。

「なるほど？　()はファイル名で使えるもんな」

けれどすぐに思い至る

「[]だってつかえるやないかい！　どういうことやねん！」

## MSDNさんにPathパラメータのことを聞いてみよう

[Select\-String \(Microsoft\.PowerShell\.Utility\) \- PowerShell \| Microsoft Docs](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/select-string?view=powershell-7)

> -Path
>
> Specifies the path to the files to search. Wildcards are permitted. The default location is the local directory.
>
> Specify files in the directory, such as log1.txt, *.doc, or *.*. If you specify only a directory, the command fails.
>
> TABLE 13
> Type:	String[]
> Position:	1
> Default value:	Local directory
> Accept pipeline input:	True
> Accept wildcard characters:	True

冒頭のとおり「ワイルドカードが許されてるよ！」とのことである。そこである疑問が思いつく。

「もともと、cmdだとワイルドカードって、\*か\?だけじゃなかったっけ？」

と調べてみた。

すると、PowerShellでは\[\]の表現も許されるようになったそうでさる。

参考：[Supporting Wildcard Characters in Cmdlet Parameters \- PowerShell \| Microsoft Docs](https://docs.microsoft.com/ja-jp/powershell/scripting/developer/cmdlet/supporting-wildcard-characters-in-cmdlet-parameters?view=powershell-7)

てめえ。\*と\?はファイル名で使えないし、そういう思想なのはよく分かる。
だけど、\[\]はファイル名で使えるだろうがよう。納得行かねえよなあ？

それでLiteralPathパラメータを作るくらいなら、RegExpPathパラメータでも作れコノヤロー。

なんかこういう中途半端な設計思想が許せねえ。

と文句を言っても仕方があるまい。なににせよ、Pathパラメータで正規表現は使えないことがよくわかった。

## Pathを配列で指定するってなに

「では、OR表現が使えないのかあ。しかたあるめえなあ。力ずくでスクリプトでも組むかあ？」と諦めかけたところ、MSDNのあるところが目に入る。

> Type:	String[]

配列？　え、配列を引数として入れられるってこと？

つまり、複数のPathを指定できるかもってこと？

ただMSDNの記述を探してもこの他には、どうも詳しく書いていない。そう、つまり、試せってことですね。

では、試してみましょう？

```PowerShell
PS C:\Work> Select-String -Path @("./2020080[1-9]/abc.log","./2020081[1-5]/abc.log") -Pattern "Hoge"
C:\work\20200802\abc.log:3 Hoge
C:\work\20200805\abc.log:3 Hoge
C:\work\20200811\abc.log:3 Hoge
C:\work\20200813\abc.log:3 Hoge
```

はい、できました

配列指定できるってなんだよって思う。まあ、Get-ChildItemからパイプでつなげてっオブジェクトを渡すためってところのためなんだろう。

PathのOr表現をなんとかワンラインで実現できたので、当初の目的は達成できた。それは喜ばしいことだ。

けれど…けれど、なんか違和感のある指定方法でしっくりこないんだよなア。

## まとめ

- Microsoftの関連で困ったらMSDNを読もう
- でもあまり具体的なことはないから、腕力で、試してみよう
- できたら正義だ！
- でも、Microsoftの作るドキュメントはすっきりしません