WSLでopenコマンドを用意する
TL;DR
WSLでMacのopenコマンドみたいなのが欲しければ、以下を.zshrc
に書く。
function open() {
if [ $# != 1 ]; then
explorer.exe .
else
if [ -e $1 ]; then
cmd.exe /c start $(wslpath -w $1) 2> /dev/null
else
echo "open: $1 : No such file or directory"
fi
fi
}
zshでしか試していないが、たぶんbashでも似たような感じでいけると思う。
エクスプローラによるopen
Macのターミナルでは、open filename
とすると、そのファイルを関連付けられたアプリで開くことができる。また、open .
などとするとFinderでカレントディレクトリが開いて便利だ。
WindowsのWSLで似たようなことがしたくて、
alias open=explorer.exe
としていた。これでもほとんどの場合はうまくいくのだが、二つ問題があった。
一つは、デスクトップに同名のファイルがあるとそちらを開いてしまうこと。おそらくエクスプローラーのパスの検索順の問題だと思われる。
もう一つは、カレントディレクトリ以外のファイルを開けない事。例えば、カレントディレクトリにhoge.pdf
があるなら
open hoge.pdf
はできるが、
open dir/hoge.pdf
open ../hoge.pdf
などはできない。
cmd.exeによるopen
ということを愚痴ったら、「cmd.exeを使うのはどうか?」という方法を教えていただいた。
cmd.exe /c start filename
として実行することで、ファイルを開くことができる。ただし、wslpathを使って、WSLのパスをWindows側に変換してやる必要がある。そこで、シェルの関数にして
function open() { cmd.exe /c start $(wslpath -w $1) }
とすれば、ほぼ所望の動作になる。
しかし、これでファイルを開くと、いちいち
$ open test.pdf
'\\wsl.localhost\Ubuntu\home\username\path\to\file'
上記の現在のディレクトリで CMD.EXE を開始しました。
UNC パスはサポートされません。Windows ディレクトリを既定で使用します。
と言われてしまう。また、存在しないファイルを指定した場合、コマンドプロンプトが開いてしまう。さらに、引数を指定しないで実行した場合「このusageリンクを開くには新しいアプリが必要です」みたいなダイアログが出てしまう。
これをもう少しなんとかしましょう、というのが本稿の目的である。
cmd.exeによるopen(改)
まず引数の数チェックをしよう。引数なしの場合、Macのopenのようにusageを表示してもよいが、open .
と同じにしてしまった方が便利だろう。それならエクスプローラで良い。
function open() {
if [ $# != 1 ]; then
explorer.exe .
fi
}
次に、引数が指定された場合、そのファイルの存在確認をしよう。ファイルがあればそのまま開き、そうでなければエラーを表示する。この時、cmd.exe
の出力を2> /dev/null
に流してしまおう。
if [ -e $1 ]; then
cmd.exe /c start $(wslpath -w $1) 2> /dev/null
else
echo "open: $1 : No such file or directory"
fi
以上をまとめると冒頭のコマンドになる。
Discussion
下記アリスを使っていますが、ファイルの開きを考えていませんでした。
参考になりました。
bashだとこの関数だけで「open」の後ろのファイル名補完が効いたのですが、zshでは何故かファイル名補完が効きませんでした(WSLのUbuntuのzsh 5.8で実行)。以下を追加で書いておく必要がありました。
情報ありがとうございます。うちも同じ環境(WSL+zsh 5.8)ですが、普通にファイル名補完が効きますね。
compinit
が何かしているのかと、.zshrc
を無効にしてopenだけ定義してやってみてもファイル補完されました。謎です。ありがとうございます。
私の.zshrcに書いてある別の設定が影響しているのかもしれません。探ってみようと思います。