🤖

WSLでopenコマンドを用意する

2022/03/09に公開
5

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

とすることでメッセージを隠す。

参考URL

GitHubで編集を提案

Discussion

gekalgekal

下記アリスを使っていますが、ファイルの開きを考えていませんでした。
参考になりました。

alias open=explorer.exe
H.HiroH.Hiro

bashだとこの関数だけで「open」の後ろのファイル名補完が効いたのですが、zshでは何故かファイル名補完が効きませんでした(WSLのUbuntuのzsh 5.8で実行)。以下を追加で書いておく必要がありました。

compdef _open_completion open
function _open_completion {
  _files
  return 1;
}
ロボ太ロボ太

情報ありがとうございます。うちも同じ環境(WSL+zsh 5.8)ですが、普通にファイル名補完が効きますね。compinitが何かしているのかと、.zshrcを無効にしてopenだけ定義してやってみてもファイル補完されました。謎です。

H.HiroH.Hiro

ありがとうございます。
私の.zshrcに書いてある別の設定が影響しているのかもしれません。探ってみようと思います。

osioosio

欲しかった機能で大変助かりました!
(おまかんの可能性もあるのですが、)当方手元ではwslのコンテナ内でexplorer.exeを直接実行できませんでしたが、絶対パス指定をしたら実行できました。誰かの参考になれば・・・

$ /mnt/c/Windows/explorer.exe
$ /mnt/c/Windows/System32/cmd.exe

/mnt/c/の部分は設定によって異なる場合があります)