WSLでopenコマンドを用意する
TL;DR
WSLでMacのopenコマンドみたいなのが欲しければ、以下を.zshrc
に書く。
function open() {
if [ $# != 1 ]; then
explorer.exe .
else
if [ -e $1 ]; then
explorer.exe $(wslpath -w $1) 2> /dev/null
else
echo "open: $1 : No such file or directory"
fi
fi
}
zshでしか試していないが、たぶんbashでも似たような感じでいけると思う。
動作原理
Macのターミナルでは、open filename
とすると、そのファイルを関連付けられたアプリで開くことができる。また、open .
などとするとFinderでカレントディレクトリが開いて便利だ。
WindowsのWSLで似たようなことがしたくて、
alias open=explorer.exe
としていた。これでもほとんどの場合はうまくいくのだが、二つ問題があった。
一つは、デスクトップに同名のファイルがあるとそちらを開いてしまうこと。おそらくエクスプローラーのパスの検索順の問題だと思われる。
もう一つは、カレントディレクトリ以外のファイルを開けない事。例えば、カレントディレクトリにhoge.pdf
があるなら
open hoge.pdf
はできるが、
open dir/hoge.pdf
open ../hoge.pdf
などはできない。そこで、wslpath -w
でパスを解決してからexplorer.exeにわたすことで、カレントディレクトリ以外のファイルにも対応している。
まず引数の数をチェックし、引数なしの場合はカレントディレクトリを開くようにする。
function open() {
if [ $# != 1 ]; then
explorer.exe .
fi
}
次に、引数が指定された場合、そのファイルの存在確認をしよう。ファイルがあればそのまま開き、そうでなければエラーを表示する。
if [ -e $1 ]; then
explorer.exe $(wslpath -w $1) 2> /dev/null
else
echo "open: $1 : No such file or directory"
fi
以上をまとめると冒頭のコマンドになる。
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 /c start $(wslpath -w $1) 2> /dev/null
とすることでメッセージを隠す。
Discussion
下記アリスを使っていますが、ファイルの開きを考えていませんでした。
参考になりました。
bashだとこの関数だけで「open」の後ろのファイル名補完が効いたのですが、zshでは何故かファイル名補完が効きませんでした(WSLのUbuntuのzsh 5.8で実行)。以下を追加で書いておく必要がありました。
情報ありがとうございます。うちも同じ環境(WSL+zsh 5.8)ですが、普通にファイル名補完が効きますね。
compinit
が何かしているのかと、.zshrc
を無効にしてopenだけ定義してやってみてもファイル補完されました。謎です。ありがとうございます。
私の.zshrcに書いてある別の設定が影響しているのかもしれません。探ってみようと思います。
欲しかった機能で大変助かりました!
(おまかんの可能性もあるのですが、)当方手元ではwslのコンテナ内でexplorer.exeを直接実行できませんでしたが、絶対パス指定をしたら実行できました。誰かの参考になれば・・・
(
/mnt/c/
の部分は設定によって異なる場合があります)