PowershellでAliasを作る

WindowsのコマンドラインシェルをPowershellに変えて何年も経つのだが、サッパリ覚えられない。普段Linuxでシェルスクリプトを書く機会が多いと、シェルスクリプトに比べて、Powershellはいろいろ長ったらしく書かなきゃならないことや、書く順番が逆みたいな物が多々あって、なかなか悩ましい。まあ歳を取ったせいか、新しいことがだんだんと身につかなくなっているのは認めたくは無いのだが、認めざる得ない。

で、対話的な処理を行うときに、Unixのシェルと同じようにaliasを設定したいのだが、やはり完全には同じようにはならないので、メモ的にまとめて、自分のために活用したい。

最初の例は特定のコマンドを実行するときのみ、評価順位の高い実行パスを追加したいと言うパターン。最近Emacs30でNative Compileが使えるようになったのだが、MSYS2の/mingw64/bin下のx86_64-w64-mingw32-gcc.exeを実行する必要がある。まあユーザーのPATH環境変数に追加すれば良いのだが、私はMSYS2を使う時はUCRT64で使うことが多いので、MinGW64の環境のPATHをここで設定したくない。そんなわけで一時的に実行パスを追加して、コマンド実行後に元に戻したい。

function emacs() {

    $originalPath = $env:PATH
    $env:PATH = "C:\Users\hogehoge\scoop\apps\msys2\current\mingw64\bin;$env:PATH"

    try {
        & C:\Users\hogehoge\scoop\apps\emacs\current\bin\emacs.exe
    } finally {
        $env:PATH = $originalPath
    }
}

こんな感じで、複数の処理を行いたい場合は関数にして処理を書いて、この関数をAliasで紐付ければ良い。と言っても、関数名をemacsで作成したので、emacs.exeで実行したときに上記の処理をしてくれない位の問題しかないので、こんな感じにしておけば良さそうだ。

Set-Alias emacs.exe emacs

PowershellのSet-AliasはUnix shellの書き方と逆なので注意しましょう。まあこんな感じで書けば順番は気にしなくて良いのだが、オプション指定のオプションの名前が長くていちいち面倒である。

Set-Alias -Name emacs.exe -Value emacs

これだと、コマンドライン引数でファイルやディレクトリを渡せないじゃないか・・・と言う問題が発生する。ということで、コマンドライン引数の処理を足しておく必要がある。

function emacs() {

    param (
        [Parameter(ValueFromRemainingArguments = $true)]
        [string[]]$Args
    )

    $originalPath = $env:PATH
    $env:PATH = "C:\Users\hogehoge\scoop\apps\msys2\current\mingw64\bin;$env:PATH"

    try {
        & C:\Users\hogehoge\scoop\apps\emacs\current\bin\emacs.exe $Args
    } finally {
        $env:PATH = $originalPath
    }
}

という感じで、残った引数があればArgs変数に文字列として格納して、コマンドの実行時に展開するようにすれば良い。

lsの代替コマンドとして、ezaと言うのがあるが、これも同じような感じで設定しておけば良い。zshやbashでの指定は・・・

alias ei="eza --icons --git"

と言う具合で簡単である。(先の環境変数を一時的に変えたい場合も余り面倒では無い。) Unixシェルの場合はaliasはただの文字列置換なので、コマンドライン引数をaliasに対しても続けることが出来るのだが、これをPowershellで行う場合は、残ったコマンドライン引数の処理が明示的に必要。つまり

function ei() {
    param (
        [Parameter(ValueFromRemainingArguments = $true)]
        [string[]]$Args
    )
    eza --icons --git @Args
}

みたいに書いておく必要がある。(じゃないと、つねにカレントディレクトリの内容が表示される。)

こういうのも暇なときに調べないとなかなか解決しないところが困ったところである。(copilotに聞くにしても、うまくこの結果にたどり着くのがなかなかめんどい。ほぼ書き方が分かった質問になってしまうのであまり役に立たない。)