Windows 11ではWindows Terminalがデフォルトのターミナルアプリケーションとなり、PowerShell 7がデフォルトのシェルになる。当然、MSYS2はこの環境で使うというのがデフォルト状態になるはずだ。しかし、MSYS2コマンドのいくつかはPowerShellと衝突するため、使い勝手の悪いところがある。今回はこの部分を調整する方法を取り上げる。
PowerShellのエイリアス
WindowsのシェルであるPowerShellはオブジェクト指向のプログラミング言語だ。シンタックスがLinuxで使われるシェルに似せてあるため、一見するとUNIX系のシェルのように使えるが、かなりゴリゴリのプログラミング言語であり、管理や操作という面では強力この上ない。
このPowerShellには「エイリアス」という別名の機能があり、コマンドやコマンドレット、関数などに別の名前を与えることができるようになっている。デフォルトで割り振られているエイリアス名のいくつかがLinux系コマンドの名前と同じになっているため、MSYS2やWSLがセットアップされていない状態でも、あたかもLinuxコマンドのように使うことができている。
例えば、以下の表はPowerShellエイリアスで特によく使われるLinuxコマンド名と、同じ名前が使われているものをまとめたものだ。実際には同名のコマンドではなく、PowerShellのコマンドレットが実行される。
PowerShellエイリアス | 対応するコマンドレット |
---|---|
cat | Get-Content |
cp | Copy-Item |
diff | Compare-Object |
echo | Write-Output |
ls | Get-ChildItem |
mv | Move-Item |
rm | Remove-Item |
sort | Sort-Object |
tee | Tee-Object |
MSYS2がインストールされていないときには便利な機能なのだが、MSYS2がインストールされた後は勝手が異なる。エイリアスのほうが優先的に解釈されるので、MSYS2のコマンドではなくPowerShellのコマンドレットが実行されるのだ。MSYS2をインストールするということは、Linuxコマンドを使いたいからなのに、PowerShellエイリアスのほうが優先して使われるのは困ってしまう。
PowerShellのエイリアスがMSYS2コマンドとか被る問題
例えば、「ls」は「Get-ChildItem」というコマンドレットへのエイリアスになっている。「dir」も実体は「Get-ChildItem」だ。
PS C:\Users\daichi> alias | grep ls
Alias cls -> Clear-Host
Alias ls -> Get-ChildItem
Alias sls -> Select-String
PS C:\Users\daichi> alias | grep dir
Alias chdir -> Set-Location
Alias dir -> Get-ChildItem
Alias md -> mkdir
Alias rmdir -> Remove-Item
PS C:\Users\daichi> Get-Command ls
CommandType Name Version Source
----------- ---- ------- ------
Alias ls -> Get-ChildItem
PS C:\Users\daichi> Get-Command Get-ChildItem
CommandType Name Version Source
----------- ---- ------- ------
Cmdlet Get-ChildItem 7.0.0.0 Microsoft.PowerShell.Management
PS C:\Users\daichi>
したがって、lsの結果も、dirの結果も次のように同じになる。
PS C:\Users\daichi\Documents> ls
Directory: C:\Users\daichi\Documents
Mode LastWriteTime Length Name
---- ------------- ------ ----
d---- 2021/07/19 19:32 chrome-ext
d---- 2021/08/15 18:53 config
da--- 2021/07/31 15:06 ISOs
d---- 2021/08/16 7:58 keyboard-shortcuts
d---- 2021/08/15 18:46 lwt
d---- 2021/09/12 15:23 misc
d---- 2021/08/31 16:40 misc-old
d---- 2021/08/29 10:57 mynavi
d---- 2021/08/02 11:09 postal-code-data
d---- 2021/07/20 8:26 powershell
d---- 2021/09/12 19:03 setup
d---- 2021/09/12 19:24 tttcmds
d---- 2021/09/12 13:39 tttcmds-old
d---- 2021/08/14 15:02 vscode-csv2tsv
d---- 2021/09/04 9:39 word-of-mouth
PS C:\Users\daichi\Documents> dir
Directory: C:\Users\daichi\Documents
Mode LastWriteTime Length Name
---- ------------- ------ ----
d---- 2021/07/19 19:32 chrome-ext
d---- 2021/08/15 18:53 config
da--- 2021/07/31 15:06 ISOs
d---- 2021/08/16 7:58 keyboard-shortcuts
d---- 2021/08/15 18:46 lwt
d---- 2021/09/12 15:23 misc
d---- 2021/08/31 16:40 misc-old
d---- 2021/08/29 10:57 mynavi
d---- 2021/08/02 11:09 postal-code-data
d---- 2021/07/20 8:26 powershell
d---- 2021/09/12 19:03 setup
d---- 2021/09/12 19:24 tttcmds
d---- 2021/09/12 13:39 tttcmds-old
d---- 2021/08/14 15:02 vscode-csv2tsv
d---- 2021/09/04 9:39 word-of-mouth
PS C:\Users\daichi\Documents>
MSYS2をインストールしたら、lsで「C:\msys64\usr\bin\ls.exe」が実行されてほしい。そうなれば、Linuxで使っているときと同じような出力が得られる。
PS C:\Users\daichi\Documents> C:\msys64\usr\bin\ls.exe
ISOs 'My Videos' desktop.ini misc postal-code-data tttcmds word-of-mouth
'My Music' chrome-ext keyboard-shortcuts misc-old powershell tttcmds-old
'My Pictures' config lwt mynavi setup vscode-csv2tsv
PS C:\Users\daichi\Documents> C:\msys64\usr\bin\ls.exe -l
total 421
drwxr-xr-x 1 daichi daichi 0 Jul 31 15:06 ISOs
lrwxrwxrwx 1 daichi daichi 21 Jun 10 19:22 'My Music' -> /c/Users/daichi/Music
lrwxrwxrwx 1 daichi daichi 24 Jun 10 19:22 'My Pictures' -> /c/Users/daichi/Pictures
lrwxrwxrwx 1 daichi daichi 22 Jun 10 19:22 'My Videos' -> /c/Users/daichi/Videos
drwxr-xr-x 1 daichi daichi 0 Jul 19 19:32 chrome-ext
drwxr-xr-x 1 daichi daichi 0 Aug 15 18:53 config
-rw-r--r-- 1 daichi daichi 418 Jul 19 20:46 desktop.ini
drwxr-xr-x 1 daichi daichi 0 Aug 16 07:58 keyboard-shortcuts
drwxr-xr-x 1 daichi daichi 0 Aug 15 18:46 lwt
drwxr-xr-x 1 daichi daichi 0 Sep 12 15:23 misc
drwxr-xr-x 1 daichi daichi 0 Aug 31 16:40 misc-old
drwxr-xr-x 1 daichi daichi 0 Aug 29 10:57 mynavi
drwxr-xr-x 1 daichi daichi 0 Aug 2 11:09 postal-code-data
drwxr-xr-x 1 daichi daichi 0 Jul 20 08:26 powershell
drwxr-xr-x 1 daichi daichi 0 Sep 12 19:03 setup
drwxr-xr-x 1 daichi daichi 0 Sep 12 19:24 tttcmds
drwxr-xr-x 1 daichi daichi 0 Sep 12 13:39 tttcmds-old
drwxr-xr-x 1 daichi daichi 0 Aug 14 15:02 vscode-csv2tsv
drwxr-xr-x 1 daichi daichi 0 Sep 4 09:39 word-of-mouth
PS C:\Users\daichi\Documents>
では、どうやって実現すればよいのかという話だが、PowerShellのエイリアスを削除して、新しくMSYS2のコマンドへエイリアスを張ればよいのだ。まず、次のようにコマンドを実行することで、エイリアスの削除を行える(ここではcat、cp、ls、mv、rmのエイリアスを削除している)。
# MSYS2コマンドに置き換えるエイリアスを削除
Get-Alias cat > $null 2>&1 && Remove-Alias cat
Get-Alias cp > $null 2>&1 && Remove-Alias cp
Get-Alias ls > $null 2>&1 && Remove-Alias ls
Get-Alias mv > $null 2>&1 && Remove-Alias mv
Get-Alias rm > $null 2>&1 && Remove-Alias rm
そして、新しくMSYS2コマンドへエイリアスを設定する。
# MSYS2コマンドへのエイリアスを作成
Set-Alias -Name cat -Value C:\msys64\usr\bin\cat.exe
Set-Alias -Name cp -Value C:\msys64\usr\bin\cp.exe
Set-Alias -Name mv -Value C:\msys64\usr\bin\mv.exe
Set-Alias -Name rm -Value C:\msys64\usr\bin\rm.exe
PowerShellのエイリアスは、本当に別名をつけるだけの機能だ。Linuxのシェルであれば、エイリアスはただの文字列の置き換えであることが多いため、エイリアスにオプションなどコマンド以外の要素を含めることができるのだが、PowerShellではそれができない。
そういった場合にはエイリアスではなく関数を定義すればよい。例えば、次のように関数を用意すれば、lsで「C:\msys64\usr\bin\ls.exe —color $Args」が実行されるようになり、「ll」で「C:\msys64\usr\bin\ls.exe —color $Args -l」が実行されるようになる。
# ls系はオプションを指定するために関数で定義
function ls { C:\msys64\usr\bin\ls.exe --color $Args }
function ll { C:\msys64\usr\bin\ls.exe --color $Args -l }
function la { C:\msys64\usr\bin\ls.exe --color $Args -a }
WindowsのシステムコマンドがMSYS2コマンドと被る問題
PowerShellではWindowsのシステムコマンドも使われている。システムコマンドのなかにはLinuxコマンドと同じ名前のものがある。例えば、Linuxには「find」があるが、Windowsでは「C:\WINDOWS\system32\find.exe」が用意されている。同じ名前だが、別の目的のコマンドだ。
PS C:\Users\daichi\Documents> Get-Command find | Format-List
Name : find.exe
CommandType : Application
Definition : C:\WINDOWS\system32\find.exe
Extension : .exe
Path : C:\WINDOWS\system32\find.exe
FileVersionInfo : File: C:\WINDOWS\system32\find.exe
InternalName: find
OriginalFilename: FIND.EXE.MUI
FileVersion: 10.0.19041.1165 (WinBuild.160101.0800)
FileDescription: 文字列検索 (grep) ユーティリティ
Product: Microsoft® Windows® Operating System
ProductVersion: 10.0.19041.1165
Debug: False
Patched: False
PreRelease: False
PrivateBuild: False
SpecialBuild: False
Language: 日本語 (日本)
PS C:\Users\daichi\Documents>
「tree」も同様に、Windowsには「tree.com」というコマンドがある。
PS C:\Users\daichi\Documents> Get-Command tree | Format-List
Name : tree
CommandType : Function
Definition : tree.com /f
PS C:\Users\daichi\Documents>
この2つのコマンドはよく似ている。Windowsではtree.comのほうがよほど動作が高速だ。ただ、機能はLinux treeのほうが多い。ユーティリティ的に使うなら、Linuxのほうを使いたい。
こうしたシステムコマンドに関しては、エイリアスを設定して済むならそうするのが簡単である。エイリアスのほうが優先的に実行されるからだ。PowerShellでは、次のように実行すればエイリアスを設定することができる。
# WindowsコマンドをMSYS2コマンドで置き換え
Set-Alias -Name find -Value C:\msys64\usr\bin\find.exe
Set-Alias -Name tree -Value C:\msys64\usr\bin\tree.exe
削除できないPowerShellエイリアスはどうすればよいか
全てがこの方法でうまくいくかと言えばそんなことはなく、いくつかのエイリアスは削除できないようになっている。次のように「diff」「sort」「tee」はそのままでは削除できないのだ。
PS C:\Users\daichi> Remove-Alias diff
Remove-Alias: Alias was not removed because alias diff is constant or read-only.
PS C:\Users\daichi> Remove-Alias sort
Remove-Alias: Alias was not removed because alias sort is constant or read-only.
PS C:\Users\daichi> Remove-Alias tee
Remove-Alias: Alias was not removed because alias tee is constant or read-only.
PS C:\Users\daichi>
無理やり削除することも可能だが、わざわざ削除できない設定になっているので、削除しないほうが無難だ。こんなときは、次のように異なる名前で関数を作成しておこう。何もしないよりもよほど使いやすくなる。
# 削除できないエイリアスについては別名を付与
function msys2_diff { C:\msys64\usr\bin\diff.exe $Args }
function msys2_sort { C:\msys64\usr\bin\sort.exe $Args }
function msys2_tee { C:\msys64\usr\bin\tee.exe $Args }
設定を$PROFILEへ書き込んでおく
後は、ここまでに取り上げた設定を「$PROFILE」に書き込んでおけばPowerShellの起動に適用される。$PROFILEのパスは環境によって異なるのだが、「Microsoft.PowerShell_profile.ps1」という名前のファイルになっているはずだ。ターミナルで「notepad $PROFILE」を実行して編集を行ってしまうのが簡単だろう。次のような内容を追加しておけばよい。
if (Test-Path -PathType Container C:\msys64\) {
# MSYS2コマンドに置き換えるエリアスを削除
Get-Alias cat > $null 2>&1 && Remove-Alias cat
Get-Alias cp > $null 2>&1 && Remove-Alias cp
Get-Alias ls > $null 2>&1 && Remove-Alias ls
Get-Alias mv > $null 2>&1 && Remove-Alias mv
Get-Alias rm > $null 2>&1 && Remove-Alias rm
# MSYS2コマンドへのエイリアスを作成
Set-Alias -Name cat -Value C:\msys64\usr\bin\cat.exe
Set-Alias -Name cp -Value C:\msys64\usr\bin\cp.exe
Set-Alias -Name mv -Value C:\msys64\usr\bin\mv.exe
Set-Alias -Name rm -Value C:\msys64\usr\bin\rm.exe
# ls系はオプションを指定するために関数で定義
function ls { C:\msys64\usr\bin\ls.exe --color $Args }
function ll { C:\msys64\usr\bin\ls.exe --color $Args -l }
function la { C:\msys64\usr\bin\ls.exe --color $Args -a }
# WindowsコマンドをMSYS2コマンドで置き換え
Set-Alias -Name find -Value C:\msys64\usr\bin\find.exe
Set-Alias -Name tree -Value C:\msys64\usr\bin\tree.exe
# 削除できないエイリアスについては別名を付与
function msys2_diff { C:\msys64\usr\bin\diff.exe $Args }
function msys2_sort { C:\msys64\usr\bin\sort.exe $Args }
function msys2_tee { C:\msys64\usr\bin\tee.exe $Args }
}
この設定を追加するだけで、MSYS2をインストールした後のPowerShellプロンプトをある程度Linux環境のように使うことができるようになる。
本連載はPowerShellが主テーマではないので、PowerShellに関する説明はここで止めておく。興味がある場合には別連載「PowerShell Core入門 - 基本コマンドの使い方」などを参考にしてもらえれば幸いだ。
いずれにせよ、Linuxを使う上でもWindowsは避けて通ることが難しいプラットフォームである。であれば、なるべくLinuxユーザーが扱いやすいようにカスタマイズしたり、操作の中心となるシェルについて知っておいたりすることは悪くない。PowerShell 7はLinuxでも使えるし、興味があるならPowerShellの活用にも取り組んでみると良いと思う。このパワフルなシェルは、Linuxで使う上でも新しいアイデアを与えてくれるはずだ。
付録: MSYS2インストール方法など
環境変数 | 内容 |
---|---|
HOME | C:\Users\ユーザ名 |
LC_CTYPE | ja_JP.UTF-8 |
Path | C:\msys64\usr\bin |
C:\msys64\mingw64\bin |
MSYS2のインストール方法
winget install MSYS2
pacman -Syu
コマンド | 内容 |
---|---|
pacman -S | パッケージインストール |
pacman -Ss | パッケージ検索 |
pacman -R | パッケージアンインストール |
pacman -Rs | パッケージおよびそのパッケージのみが必要としているパッケージをアンインストール |
pacman -Rns | パッケージおよびそのパッケージのみが必要としているパッケージおよびバックアップファイルをアンインストール |
pacman -Fx | 指定したファイルが含まれているパッケージを一覧表示 |
pacman -Fl | 指定したパッケージがインストールするファイルを一覧表示 |
pacman -Q | インストール済みパッケージ一覧表示 |
pacman -Syu | メタデータアップデートとパッケージアップグレード |