19
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

dotfilesAdvent Calendar 2019

Day 18

WSLにもそこそこ使えるopenが欲しい!

Last updated at Posted at 2019-12-17

これは dotfiles Advent Calendar 2019 の 18 日目の記事です。

WSL のユーザー向けに、過去の記事よりちょっと便利な open コマンドの実装を紹介します。
ちなみに自分の dotfiles は こんな感じ で、デスクトップ版の Ubuntu でも使っています。

open コマンドとは

まず open コマンド(Ubuntu などでは xdg-open など)とは、指定されたパスや URL をデフォルトのアプリケーションで開くコマンドです。
例えば Ubuntu の場合、xdg-open . で Nautilus などのファイラーが、xdg-open https://qiita.com で Chrome などのブラウザが、xdg-open ~/.bashrc で VS Code などのエディターが起動するはずです。
便利ですね。
しかし WSL の場合は GUI がないため、これらのコマンドが上記のように機能しません。
WSL でも open でエクスプローラーや Windows 側の Chrome なり VS Code なりを起動したいですよね?

これについては先人がおり、Qiita にも既に WSL から open という同様の記事が投稿されています。
今回はここで紹介されている open の実装を見直し、より便利にアップグレードしてみました。
Windows10 1903 で WSL 内のディレクトリにも Windows で有効なパスが割り当てられた こともあり、具体的には以下のようなことが可能になっています。

  • スペースを含むパスに対応した
  • URL に対応した
  • open / など Windows 側に実体のないファイルも開けるようになった

実装とその説明

とりあえずこんな感じになっています。
WSL ユーザーはこれを ~/.bashrc に追記し、source ~/.bashrc を実行すれば open が使えるようになります。

~/.bashrc
open() {
  if [ $# -ne 1 ]; then return 1; fi
  if [ -e "$1" ]; then
    local winpath=$(readlink -f "$1" | xargs -0 wslpath -w)
    powershell.exe start "\"${winpath%?}\""
  else
    powershell.exe start "$1"
  fi
}

まず 1 行目ですが、リリース情報を見て WSL かどうかの判定をしています。
判定方法は いくつか あるようですが、今回は POSIX 準拠でなるべくわかりやすそうなものを選択しました。
(まあ後で 3 か所ほど Bash の拡張を使ってしまっているのであまり意味はないかもですが。)
次の if は引数が一つだけかのチェックで、一つでないときは early return しています。
このあたりまでは元の実装と大体同じ雰囲気です。

次の if では指定されたパスが存在するかを確認し、URL などパスでない場合は else でそのまま powershell.exe start を呼び出しています。
元の実装はワンライナーでこの部分がなかったため、URL を処理できませんでした。
また元の実装では cmd.exe /c start を使っていましたが、今回は 4U6U57/wsl-open を参考に powershell.exe start を使っています。
入力がパスであった場合の処理も変更しており、ワンライナーをやめローカル変数 winpath を作ってから powershell.exe start にこれを渡すことで、powershell.exe start による余計なログが出力されないようにしています。
(なぜローカル変数を作ることで余分なログが出なくなるのかは、正直よく分かっていません。)
ちなみに winpath とは、wslpath -w で指定された WSL 側のパスを Windows 側のパスに変換したものです。
wslpath の前に readlink -f でシンボリックを展開し、xargs でコマンドをつなぐとき -0 でスペースを含むパスも扱えるようにしています。
あとは最後に "\"${winpath%?}\"" で、start が正しく動作するよう両端に " をつけたり -0 によるヌル文字を消したりしています。

拡張子とアプリの関連付けを変更する

open で起動するアプリと拡張子との関連付けは、Windows10 の「設定」の「既定のアプリ」の下の「ファイルの種類ごとに既定のアプリを選ぶ」をクリックした画面で変更できます。

おまけ

自分は if uname -r | grep -q 'Microsoft'; then のブロックにこんなコードも書いています。

~/.bashrc
if uname -r | grep -q 'Microsoft'; then
  export LS_COLORS='ow=01;33'

  ggl() {
    if [ $# -eq 0 ]; then return 1; fi
    open "https://www.google.com/search?q=$(echo "$@" | sed 's/+/%2B/g;s/ /+/g')"
  }

  if [ "${PWD,,}" = '/mnt/c/windows/system32' ]; then cd; fi
fi

まず最初の export LS_COLORS='ow=01;33'ls で表示されるフォルダーの色を変更する設定です。
この記事 を参考に、/mnt/c 以下にある Windows 側のフォルダのシンボリックリンクを見やすいように黄色にしています。

次の ggl は以下のツイートを参考に作った関数で、ターミナルから Google 検索ができるようになります。
open/mnt/c/Program\ Files\ \(x86\)/Google/Chrome/Application/chrome.exe で置き換えても動きます。

最後の if [ "${PWD,,}" = '/mnt/c/windows/system32' ]; then cd; fiWindows Terminal から WSL を使っている人向けの設定です。
VS Code のように右クリックのメニューから Windows Terminal を開けるようにした場合、ショートカットから起動すると /mnt/c/WINDOWS/system32 などがカレントディレクトリになってしまうのを修正します。
詳しくは microsoft/terminal#1060 を見るといいでしょう。
余談ですが Windows Terminal は現状でもかなり便利なのでおすすめです。
自分の dotfiles にも Windows Terminal の設定 が置いてあるので、興味のある人は是非使ってみてください。

参考文献

19
9
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?