PowerShellでつけたエイリアスと同じ名前のコマンドにパスが通っていたらどっちが使われるのか
突然に、MinGWのことを思い出しました。 あいつは便利なやつで、WindowsでもUnix的なコマンドを実行するのに使うことができます。 それにCygwinではないのでCドライブの指定を「/cygdrive/c」とかしなくても「/c」で許してくれるいいやつです。
Cygwinはcygpath使えば元のパスにしてくれますけどね。
WindowsではGitをインストールすると、msysが一緒に導入されてUnix的な環境を使うことができるようになります。 これの「/usr/bin」ディレクトリにパスを通してやれば、「WindowsのコマンドプロンプトなどからもUnix的な操作ができて便利だな」となります。
サラリーマンの頃はこの設定をしてて、テキストファイルからの文字列検索にWindows標準コマンドの「findstr」を使わずにgrepを使っていたりしました。 それはそれで不具合多かったのですが。
今となってはPowerShellを使っているのでgrepも必要ありません。
Select-String -Path pages\*.md -Pattern "^.*\[aaa\].*$"
などとすればパターンにマッチした内容を表示してくれます。
そこでふと思いだしたのです。 むかしのバージョンのPowerShellって、Select-Stringに「grep」というエイリアスを標準でつけてなかったかな?と。
手元のWindows10ではエイリアスには入っていませんでした。
もしもSelect-Stringに「grep」とエイリアスを設定していた場合にGitのほうにパスが通っていたら、どっちが利用されるんだろうと不安になりました。
Set-Alias -Name grep -Value Select-String
これは少し.NetFramework先生のご協力が必要になります。
[System.Environment]::SetEnvironmentVariable("PATH", "$env:Path;C:\Program Files\Git\usr\bin")
Windows標準コマンドでいう「where」、Unix系だと「which」をPowerShellでやります。
CommandType Name Version Source ----------- ---- ------- ------ Alias grep -> Select-String
Get-Command grep -CommandType Application
CommandType Name Version Source ----------- ---- ------- ------ Application grep.exe 0.0.0.0 C:\Program Files\Git\usr\bin\grep.exe
一応公式ドキュメントでも調べてみることにしました。 Gitへのパスを$env:Pathの最後につけてしまいましたからね。
about_Command_Precedence
https://technet.microsoft.com/ja-jp/library/hh848304.aspx
If you do not specify a path, Windows PowerShell uses the following precedence order when it runs commands:
1. Alias
2. Function
3. Cmdlet
4. Native Windows commands
パスが特定できない場合は次の優先順位でコマンドを実行しますとあります。
ということで、エイリアス>関数>コマンドレット>実行形式 ということになりますね。
だから今回もSelect-Stringへのエイリアスが優先されたということになります。
もしもコマンドタイプまで同じだったとしたら?ということも続きに書いてありますね。
When the session contains items of the same type that have the same name, such as two cmdlets with the same name, Windows PowerShell runs the item that was added to the session most recently.
セッション中に同じ種類で同じ名前を持ったアイテム、同じ名前の2つのコマンドレットがあったらどうするか?
このときはそのセッションに後から追加されたほうを実行する、とあります。 だから、モジュールをインポートしたりして後から被った名前のものがあったりすると、そちらが優先順位を上げてしまうのですね。
ということで、エイリアスは用法用量を守って正しくというところでしょうか。
個人的にはエイリアスでコマンドレットを呼び出すようなスクリプトは書かないほうが無難だなーと思っています。 意図しない動作をしてしまうからですね。