<Powershell>特定の文字列で区切られたファイル名をそのファイル名の一部で一括変換するクイズ

こんにちは

Powerhsellって結構万能になりましたよね。
バッチファイル時代だと結構苦労したものも、オブジェクトの考え方が出てきて高級言語っぽくなってやれることが増えてアイデア次第でなんでもできるようになりました。
WindowsServerを管理するとなった場合はもちろん有用ですが、ワークステーション利用ならばWindows10は当分とって変わられることがないでしょう
だからこそ、バッチファイルやPowershellでスクリプトがかけるというのは強みだと思います。
（業務効率化のいちばんの近道だと思っています。）

というわけで今回はタイトルの通り、ちょっとしたクイズというか頭の体操に挑戦してみましょう。

# 経緯
今まで定例業務としてあるサービスからファイルをダウンロードしていたのですが、システム更改を経て出力ファイル名が変更になってしまいました・・・
そのあとExcelのマクロに食わせる予定なので、一つ一つファイル名を変更するのは骨が折れます。。。

このご時世に２回以上繰り返し作業が予定されているものを自動化しないわけには行きません。(愚の骨頂です)
というわけで、ファイルリネーム自動処理を組んでみましょう。

# お題目
レギュレーションとしては、Powershellを使いましょう、以上です。

1から１００までの数字が一部に入っているファイル名のCSVがあるとします。
適当な文字列が_(アンダースコア)でつなげられている、というのが今回のターゲットです。
で、やらなくちゃいけないのは、今回の例でいくと、一部がユニークになっている(今回はユニークな数字)ので、
そのユニークな文字を抜き出してファイル名変換する、というものです。
あ、あとかっこいいのでワンライナーでやりましょうよ。（大胆なチャート変更はQiita民の特権）

言葉でごちゃごちゃ言ってもわからないと思うので(私も言っててわかりません)以下を見てください。

```terminal:事前準備(labo>以降のコマンドを実行してください。カレントディレクトリは注意してくださいね。)
PS C:\Users\Administrators\Documents\labo> 1..100 | ForEachObject{ Write-Host > "abc_test_ok_${_}_this.csv"}
```

```terminal:準備結果
PS C:\Users\Administrators\Documents\labo> dir


    ディレクトリ: C:\Users\Administrators\Documents\labo


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----       2020/07/13     21:57              0 abc_test_ok_1_this.csv
-a----       2020/07/13     21:57              0 abc_test_ok_10_this.csv
-a----       2020/07/13     21:57              0 abc_test_ok_11_this.csv
-a----       2020/07/13     21:57              0 abc_test_ok_12_this.csv
-a----       2020/07/13     21:57              0 abc_test_ok_13_this.csv
-a----       2020/07/13     21:57              0 abc_test_ok_14_this.csv
-a----       2020/07/13     21:57              0 abc_test_ok_15_this.csv
〜以下略〜
```

```terminal:こうなってほしい
PS C:\Users\Administrators\Documents\labo> dir


    ディレクトリ: C:\Users\Administrators\Documents\labo


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----       2020/07/13     21:57              0 1.csv
-a----       2020/07/13     21:57              0 10.csv
-a----       2020/07/13     21:57              0 11.csv
-a----       2020/07/13     21:57              0 12.csv
-a----       2020/07/13     21:57              0 13.csv
-a----       2020/07/13     21:57              0 14.csv
-a----       2020/07/13     21:57              0 15.csv
```

# 私の答え

すぐに答え出しますね。
答えというか私の作ったものってだけですが。
答えを考えたい人は動画を一時停止して考えてみてください。

↓
↓
↓
↓
↓
↓
↓
↓
↓
↓
↓
↓
↓
↓

```terminal:こたえ
dir -Name | foreach-object{$org = $_;$tmp = $_.split("_");$aft = -join($tmp[3], ".csv");ren $org $aft}
```

うーんゴリ押し。
やりたいと思ったことをそのままつらつらとつなげただけ。センスなし。
でもまぁいいんだ。やりたいことができるから。

## 少しだけ解説。

```terminal
dir -Name | foreach-object{...}
```
カレントディレクトリのファイル名一覧を取得。ファイル名だけね、という-Nameオプション。
いやーPowershellなんだからGet-ChildItem使えって？いやまぁそう怒んなって。旧石器時代(MS-DOS)の人間なんだからこれぐらい許してくれよぉ。そのためにMSさんもAlias貼ってくれてるんだから有効活用しましょうよってな話。
で、そのあとパイプでforeach-Objectでぐるぐるまわしてるよってかんじ
この時点で、1行ずつ（イメージとしては、「abc_test_ok_1_this.csv」）処理できるようになったねって感じです。各個撃破は戦いの基本。

```terminal
$org = $_;
$tmp = $_.split("_");
```
Powrshell面白いなって思ったのはこれ。$_ってなんだよって感じ。これはパイプの前からもらったものがそのままこの変数として表現できるのです。（イメージとしては、「abc_test_ok_1_this.csv」。本日二回目）Linuxならxargsみたいな感じなんでしょうけどね。いくらなんでも簡素化しすぎでしょ・・・見通し良すぎてマサイ族になったわ。
で、ファイル名変更なので、ファイル名を加工する前を覚えとかなくちゃいけないので、一旦orgに。originalっことね。ネーミングセンスのかけらもない。
で、splitを使って、_という区切り文字で配列につっこむ。この時点で、$tmp[0] としてやれば、abcの文字列が得られるようになる。
今回は3つめにしたいので、tmp[3]が目的のワードとなるはず。にしてもtmpってのは本当に酷いネーミングだ。ネグレクトですねこれは。。。

```terminal
$aft = -join($tmp[3], ".csv");
ren $org $aft
```
文字列変換後、ということでafterのaft。もうこの辺りは直感よ。後から見てもよく分からなくなってしまう典型。で、StringのJoinというメソッドを使って、$tmp[3]と".csv"という文字列を結合したってわけ。これで、名前変更後について準備が整ったってわけ。
で、最後にrenコマンドで名前変更。これも旧石器時代、というかオーパーツよねこれ。

# 終わりに

いかがでしたでしょうか。(アフィリエイトサイト並の感想)
正直ね、知性が見られないよね。ゴリラよ。ゴリラもビックリのゴリ押し。
でもいいんですよ、これで動くんですから。いや本当はcsvに変換して〜とか考えたんですけど、ちょっと大変そうなのでかんがえるのやめちゃいました。勝てばよかろうなのだぁー！

皆さんには是非こうなって欲しくないですが、このレギュレーションでよりよい解決策があれば是非コメント欄で書いてください。私とバトりましょうよ。私の作ったコマンドなんてLevel３ポッポですけど。