PowerShellでcurl, wgetを使いたい

#背景
WSLでLinux環境が手軽に使えるようになったので、PowerShellとLinuxのコマンドラインを行き来する機会が多くなった。

そうなると、PowerShellで作業している時につい`curl http://example.com`のように入力してしまい勝ちだが、PowerShellは標準で**curl**や**wget**に**Invoke-WebRequest**コマンドレットをエイリアスとして割り当てているため、期待どおりの出力じゃなくて微妙な気分になる。

個人的には**Invoke-WebRequest**が使いたいならそう書くよ！と思ったので、**curl**と**wget**については標準のエイリアスを上書きしたいと思った。（ちなみに**Invoke-WebRequest**には**iwr**という標準エイリアスがあるので尚更…）

設定系は次にやる時まで内容を覚えていない事が多いので、メモとして記録してみる。

#Windows用のcurl, wgetをインストール
[Chocolatey](https://chocolatey.org/)を使っているので、`cinst`でさくっとインストール完p了。

```ps1:PowerShell(管理者)
PS C:\>cinst curl wget -y
```

個別に入れたい場合は、それぞれ以下から入手可能。
[curl - Download](https://curl.haxx.se/download.html#Win64)
[GNU Wget 1.19.2 for Windows](https://eternallybored.org/misc/wget/)

#エイリアスの上書きのテスト
**Set-Alias**コマンドレットで上書きしてみる。
Chocolateyでは`%ChocolateyInstall%\bin`フォルダにShimを作ってくれるので、そこを参照する。
（個別にインストールした場合はインストール先のフルパスを指定する）

```ps1:PowerShell
PS C:\>sal curl (Join-Path $env:ChocolateyInstall "bin\curl.exe")
```

※`sal`はSet-Aliasのエイリアス

が、これで実行してみたら以下のエラー

```ps1:PowerShell
PS C:\> sal curl (Join-Path $env:ChocolateyInstall "bin\curl.exe")
sal : AllScope オプションをエイリアス 'curl' から削除できません。
発生場所 行:1 文字:1
+ sal curl (Join-Path $env:ChocolateyInstall "bin\curl.exe")
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : WriteError: (curl:String) [Set-Alias], SessionStateUnauthorizedAccessException
    + FullyQualifiedErrorId : AliasAllScopeOptionCannotBeRemoved,Microsoft.PowerShell.Commands.SetAliasCommand
```

どうやら既定のエイリアスがAllScopeで定義されているため、Localスコープのエイリアスとして上書きする事ができない模様。
`AllScope`をオプションにつけて実行してみる。

```ps1:PowerShell
PS C:\> sal curl (Join-Path $env:ChocolateyInstall "bin\curl.exe") -O AllScope
PS C:\> gal curl

CommandType     Name                                               Version    Source
-----------     ----                                               -------    ------
Alias           curl -> curl.exe
```

※`gal`はGet-Aliasのエイリアス

できた。

#$Profileの作成
以上の手順だけだとセッションごとにやり直す必要があるので、プロファイルで設定を行うようにする。
Bashでいうところの*~/.bash_profile*とか*~/.bashrc*に相当するのがPowerShellだと$Profileで参照できるファイル。

※注意：ユーザーやホスト(ISE等)ごとに指定方法が異なるので、詳しくは[こちら](https://docs.microsoft.com/ja-jp/powershell/scripting/core-powershell/ise/how-to-use-profiles-in-windows-powershell-ise?view=powershell-5.1#selecting-a-profile-to-use-in-the-windows-powershell-ise)を参照。

`notepad $profile`とかで適当にエディタで開いて以下の内容で作成。

```ps1:Microsoft.PowerShell_profile.ps1
#Alias
$aliases = @{
  curl = Join-Path $env:ChocolateyInstall "bin\curl.exe";
  wget = Join-Path $env:ChocolateyInstall "bin\wget.exe";
}
$aliases.GetEnumerator() | % {if (Test-Path $_.Value) {sal $_.Key $_.Value -O AllScope}}
```

後で同様の追加がし易いようにハッシュテーブルに「エイリアス名=コマンドのファイルパス」形式で定義してみた。
コマンドがあれば追加するエイリアスをセットする。

ファイルを上書き保存し、PowerShellの開き直して`gal`で確認→OK。

#おまけ

当初、

```ps1:PowerShell
$aliaese | % {...}
```

でやってみたらうまく値が取れなくて悩んだが、PowerShellのハッシュテーブルは明示的に`GetEnumerator()`を付けないと列挙できないらしい。（知らなかった…）
参考：[PowerShellのHashtableがコレクション扱いされない話 - しばたテックブログ](http://blog.shibata.tech/entry/2017/01/19/031705)

C#脳だとハマるポイントかも。

#追記(2017-11-19)
curl, wgetコマンドがパスの通った場所にインストールされているのであれば、

```ps1:Microsoft.PowerShell_profile.ps1
#Alias
del alias:curl
del alias:wget
```

として単純にエイリアスを削除するだけでも良かった。
こっちの方がシンプル。

ただパスでの解決に頼っちゃうと、`cygwin`とかで同名のコマンドがインストールされたら意図せず呼ばれるプログラムが変わる可能性がある。（パスの指定順に気をつければ良いとは言え）

curlやwgetみたいに同じ挙動のプログラムならあんまり問題ないんだけど、ちょっと気持ち悪い。
それが嫌なら、どっちにしろ同名のエイリアスを作る処理を足さないといけないので、あんまり変わらないかな。

#追記(2017-12-20)
curlについて、tarと共に Insider Build 17063 から標準搭載されるそうです。
Insider Buildはまだ試してませんが、PowerShellの標準aliasも無くなるかな？

[Tar and Curl Come to Windows! | Virtualization Blog](https://blogs.technet.microsoft.com/virtualization/2017/12/19/tar-and-curl-come-to-windows/)

#追記(2018-05-04)
April 2018 Updateを適用後に確認したところ、`Invoke-WebRequest`へのエイリアスとして`curl`が残っていました。(`wget`も同様)
コマンドプロンプトも使う人は注意が必要ですね。