数日前より,WSL (Windows Subsystem for Linux)を使い始めました.Microsoft StoreでUbuntu 18.04 を入手し,「Windows の機能の有効化または無効化」で「Windows Subsystem for Linux」にチェックを入れてから,再起動.こまごまとした作業をしたのち,rbenvでrubyの2.6.0-devをインストールし,いくつかのRubyスクリプトが動くのを確認しました.
CygwinからWSLへの移行も,可能そうだなと思いつつ,気になったのはドライブレターの扱いです.Windowsの(あるいはコマンドプロンプトで指定する)ドライブ名の書き方は「C:」ですが,これはCygwinだと「/cygdrive/c」に対応し,WSLでは「/mnt/c」になります.
zshの設定ファイルに手を加えてみます.久しぶりに.zshrcを開いて見ると,uname -srの出力をもとに,linuxか,cygwinかを判定していました.WSLのシェルで,uname -srを実行すると,「Linux 4.4.0-17134-Microsoft」と出ました.設定に反映させましょう.
if [ -f $ZDOTDIR/.archi.wsl ]; then export ARCHI="wsl" elif [ -f $ZDOTDIR/.archi.linux ]; then export ARCHI="linux" elif [ -f $ZDOTDIR/.archi.cygwin ]; then export ARCHI="cygwin" elif [ -f $ZDOTDIR/.archi.dummy ]; then export ARCHI="dummy" elif which uname >& /dev/null; then case "`uname -sr`" in Linux*Microsoft); export ARCHI="wsl" ; touch $ZDOTDIR/.archi.$ARCHI ;; Linux*); export ARCHI="linux" ; touch $ZDOTDIR/.archi.$ARCHI ;; CYGWIN*); export ARCHI="cygwin" ; touch $ZDOTDIR/.archi.$ARCHI ;; *); export ARCHI="dummy" ; touch $ZDOTDIR/.archi.$ARCHI ;; esac else export ARCHI="dummy" fi
zshrc_suffix="$ZDOTDIR/.zshrc.$suffix" [ -f $zshrc_suffix ] && source $zshrc_suffix
次に開くファイルは,.zshrc.cygwinです.ドライブレターについて,環境変数をいくつも定義していました.実在しないものも,あえて定義しています.USBメモリなどを接続した際に,$Dなどを使用することになります.
export C="/cygdrive/c"; export DRIVEC="$C" export D="/cygdrive/d"; export DRIVED="$D" export E="/cygdrive/e"; export DRIVEE="$E" export F="/cygdrive/f"; export DRIVEF="$F" export G="/cygdrive/g"; export DRIVEG="$G" export H="/cygdrive/h"; export DRIVEH="$H" export I="/cygdrive/i"; export DRIVEI="$I" export J="/cygdrive/j"; export DRIVEJ="$J" export K="/cygdrive/k"; export DRIVEK="$K" export L="/cygdrive/l"; export DRIVEL="$L" export M="/cygdrive/m"; export DRIVEM="$M" export N="/cygdrive/n"; export DRIVEN="$N" export Y="/cygdrive/y"; export DRIVEY="$Y" export Z="/cygdrive/z"; export DRIVEZ="$Z" U="$C/Users/$USER" T="$U/Desktop"
それでは,.zshrc.wslを新たに作成します.上記をコピーして貼り付け,cygdriveをmntに置換します.ついでに,WSLから見たCygwinのホームディレクトリを,環境変数Rに割り当てておきます.
export C="/mnt/c"; export DRIVEC="$C" export D="/mnt/d"; export DRIVED="$D" export E="/mnt/e"; export DRIVEE="$E" export F="/mnt/f"; export DRIVEF="$F" export G="/mnt/g"; export DRIVEG="$G" export H="/mnt/h"; export DRIVEH="$H" export I="/mnt/i"; export DRIVEI="$I" export J="/mnt/j"; export DRIVEJ="$J" export K="/mnt/k"; export DRIVEK="$K" export L="/mnt/l"; export DRIVEL="$L" export M="/mnt/m"; export DRIVEM="$M" export N="/mnt/n"; export DRIVEN="$N" export Y="/mnt/y"; export DRIVEY="$Y" export Z="/mnt/z"; export DRIVEZ="$Z" U="$C/Users/$USER" T="$U/Desktop" R="$E/cygwin/home/$USER"
WSL環境でzshを開き直し…無事に,$Cや$Tで参照できるようになりました.
さて上記のとおり,たくさん変数を定義したものの,ドライブ,より正確にはディレクトリとして実在しないものもあります.実在するディレクトリについてだけ,変数名と対応するディレクトリを出力させるよう,zsh用のfunctionを作ることにします.
処理としては,AからZまでのそれぞれについて,その名前の変数がセットされ,そして変数の値がディレクトリとして実在するときに,$付きの変数名と値を,出力するようにしてみます.試行錯誤の結果,以下のコマンドになりました*1.
$ [[ -n "${T+1}" && -d $T ]] && echo "\$T=$T" $T=/mnt/c/Users/takehikom/Desktop $ [[ -n "${Q+1}" && -d $Q ]] && echo "\$Q=$Q" 〔何も表示されない〕
「AからZまで」は,Rubyを使って自動生成させました.irbを実行してから,「('A'..'Z').each{|c| puts " -n \"${#{c}+1}\" && -d $#{c} && echo \"\\$#{c}=$#{c}\""}」で,一通り出ました.
出力のためのfunctionは,アーキテクチャを問わず使えそうなので,.zshrcに追加しました.
function print-drive-letter () { [[ -n "${A+1}" && -d $A ]] && echo "\$A=$A" [[ -n "${B+1}" && -d $B ]] && echo "\$B=$B" [[ -n "${C+1}" && -d $C ]] && echo "\$C=$C" [[ -n "${D+1}" && -d $D ]] && echo "\$D=$D" [[ -n "${E+1}" && -d $E ]] && echo "\$E=$E" [[ -n "${F+1}" && -d $F ]] && echo "\$F=$F" [[ -n "${G+1}" && -d $G ]] && echo "\$G=$G" [[ -n "${H+1}" && -d $H ]] && echo "\$H=$H" [[ -n "${I+1}" && -d $I ]] && echo "\$I=$I" [[ -n "${J+1}" && -d $J ]] && echo "\$J=$J" [[ -n "${K+1}" && -d $K ]] && echo "\$K=$K" [[ -n "${L+1}" && -d $L ]] && echo "\$L=$L" [[ -n "${M+1}" && -d $M ]] && echo "\$M=$M" [[ -n "${N+1}" && -d $N ]] && echo "\$N=$N" [[ -n "${O+1}" && -d $O ]] && echo "\$O=$O" [[ -n "${P+1}" && -d $P ]] && echo "\$P=$P" [[ -n "${Q+1}" && -d $Q ]] && echo "\$Q=$Q" [[ -n "${R+1}" && -d $R ]] && echo "\$R=$R" [[ -n "${S+1}" && -d $S ]] && echo "\$S=$S" [[ -n "${T+1}" && -d $T ]] && echo "\$T=$T" [[ -n "${U+1}" && -d $U ]] && echo "\$U=$U" [[ -n "${V+1}" && -d $V ]] && echo "\$V=$V" [[ -n "${W+1}" && -d $W ]] && echo "\$W=$W" [[ -n "${X+1}" && -d $X ]] && echo "\$X=$X" [[ -n "${Y+1}" && -d $Y ]] && echo "\$Y=$Y" [[ -n "${Z+1}" && -d $Z ]] && echo "\$Z=$Z" }
実行してみます.Cygwinの端末では:
$ print-drive-letter $C=/cygdrive/c $E=/cygdrive/e $F=/cygdrive/f $T=/cygdrive/c/Users/takehikom/Desktop $U=/cygdrive/c/Users/takehikom $Z=/cygdrive/z
次に,WSLのUbuntuでは:
$ print-drive-letter $C=/mnt/c $E=/mnt/e $F=/mnt/f $R=/mnt/e/cygwin/home/takehikom $T=/mnt/c/Users/takehikom/Desktop $U=/mnt/c/Users/takehikom $Z=/mnt/z