WSL で Windows のディレクトリパスが欲しい

Posted on 2020-03-01 in zakki

(2020.03.02 追記 )

実は途中から「これ絶対に要望を満たすコマンド実装されてるよなー、誰か作ってるよなー」とか思いながら作成していたのですが本当にあって思わず笑ってしまった。wslpathというものが実装されています。

❯ which wslpath
/bin/wslpath
❯ wslpath -w "/mnt/d/"
D:\
❯ wslpath -w "/mnt/d/hoge"
wslpath: /mnt/d/hoge: No such file or directory

上を見ての通り存在しないディレクトリはNo such file or directoryと教えてくれるナイスな感じなので、もうこれを使用すればいいのでは?となった。私個人としては fish の経験値が少し積めただけ良しとしましょう …。

( 追記おわり )

WSL で操作を行う際に Windows 上のディレクトリパスが欲しいことがありましたので、fish のシェルスクリプトとして作成しました。そのメモです。ちなみに動作はこのような感じです。

❯ winpath "/mnt/e/hoge/to/fuga"
E:\hoge\to\fuga
❯ winpath "/mnt/d"
D:\
❯ winpath "/mnt/hoge/to/fuga"
Drive letter is not 1 letter.
❯ winpath "/mnt"
Don't open /mnt directory.

環境

❯ fish -v
fish, version 2.7.1

2.7 ですが、最新は 3.1 らしい。

コード

ちなみにシェルスクリプトで行うことは引数で与えられた文字列の操作だけですので難しいものではありません。

❯ cat winpath.fish
function winpath

  # check argv
  if test (string match -r "^/" $argv)
    set list (string split "/" $argv)
  else
    echo "Directory path must include leading slash."
    return 1
  end

  # $list[0],[1] = null
  # $list[2] = "mnt"
  # $list[3] = c or d or ...(drive letter)
  # $list[4],[5],... = directory path

  # check $list[2]
  if not test (string match -r "mnt" $list[2])
    echo "Directory path must contains \"mnt\"."
    return 1
  end

  # check count $list and $list[3]
  switch (count $list)
    case 2
      echo "Don't open /mnt directory."
      return 1
    case 3
      set path ""
    case "*"
      if test (string match -r "^[a-z]{1}\$" $list[3])
        set path (for i in (seq 4 (count $list))
          echo $list[$i]
        end | string join "\\")
        # aaa\bbb\ccc\ddd
      else
        echo "Drive letter is not 1 letter."
        return 1
      end
  end

  set path (string join ":\\" (string upper $list[3]) $path)
  # D:\aaa\bbb\ccc\ddd

  echo $path
end

コード中の$list[3]がディレクトリパスのドライブレターとなります。それが Windows で認識しているドライブレターと合致しているかの判断もしようかと思いましたがそこまでは出来ていません。そのため Windows に存在しないディレクトリパスも普通に表示されてしまいます。エラー処理が適当な箇所も含めもう少しどうにかしたい。

WSL fish