ブラウザで閲覧中のローカルファイルがあるフォルダに簡単に cd したい……
以前にUbuntu on Windows で Windows のフルパス名で cd する というネタを書いたのですけど、file:/// なパス指定でも同様に cd できると良いなあと思ったので、少し変更してみることにしました。
実際に実行してみたのがこちらのスクリーンショット。
こうなると、ブラウザでローカルファイルを開いている最中に、そのファイルのあるディレクトリで作業したい場合にコピペで cd できるわけですね。
このスクリーンショットは Bash on Ubuntu on Windows のものですが、今回実装した内容は普通の Linux でも使えます。自分の手元では Kali Linux で確認済みです。
実装
Windowsのパス名をUbuntu on Windowsのパス名に変換して cd することは前回の実装で出来ているのですが、今回の実装では file:///[ドライブ名]:/… を見つけたら Windows のパス名相当に変換する処理を付け足します。付け足すといっても今回作る処理が先に行われるようにします。
そうすることで、前回作成した部分がほとんどそのまま使いまわせます。
また、file:/// なパスにはURLエンコードされた文字を含む場合があります。たとえば、"Program%20Files" とか。これは当然ながらデコードしなければなりません。
このような処理と前回実装済みの処理との組み合わせにより、 URL形式の file:///[ドライブ名]:/… と、Windowsのフルパス形式の両方を Ubuntu on Windows の cd で利用できるようになるわけです。
あるいは、せっかくなので file:/// でドライブレターを含まない場合も扱えるようにしてみましょう。そうするとこれは同じ実装がネイティブな Linux や UNIX 環境でも使えます。macOS のターミナルでも多分動くはず。
実際の実装例はこちらです。前回同様に .bashrc あたりにこれを追記します。
# file:// や [drive_letter]:\... の入力文字列を UNIX のパス形式に変換する処理
__change_winpath2buwpath() {
newpath=""
local __inputpath="$1"
# https://regexper.com/#%5Efile%3A%5C%2F%5C%2F(%5C%2F((%5BA-Za-z%5D%3A)%3F%5BA-Za-z0-9%20%5C-%5C.%5C%25%5C%2F%5C~%5C(%5C)%5C%3A%5D*))(%5B%23%5C%3F%5D.*)%3F
if [[ $__inputpath =~ ^file:\/\/(\/(([A-Za-z]:)?[A-Za-z0-9 \-\.\%\/\~\(\)\:]*))([#\?].*)? ]]; then
if [ "${BASH_REMATCH[3]}" == "" ]; then
# 入力値がドライブレターを含まない file:/// のパス指定なら file:// と # 以降を削ってUNIXのフルパス相当にする
__inputpath=$( printf '%b' "${BASH_REMATCH[1]//%/\\x}")
else
# 入力値が file:///[A-Za-z]:/ のパス指定なら file:/// と # 以降を削ってWindowsのフルパス相当の文字列にする
__inputpath=$( printf '%b' "${BASH_REMATCH[2]//%/\\x}")
fi
fi
if [[ "$__inputpath" =~ ^([A-Za-z]):(.*) ]]; then
# 入力文字列が Windows のフルパスならば
# ドライブレターとディレクトリに分解する
local __windows_driveletter=${BASH_REMATCH[1],}
local __windows_path=${BASH_REMATCH[2]}
# ドライブレターとパスを含めて Ubuntu on Windows 上でのパスにする
# このときにドライブレターは小文字に変換し
# バックスラッシュをスラッシュに置換している
newpath="/mnt/${__windows_driveletter}${__windows_path//\\/\/}"
else
newpath="$__inputpath"
fi
}
__cd() {
if [ "$1" == "" ]; then
# パラメータが未指定の場合は cd コマンドをパラメータ無しで実行する
\cd
else
# Windowsのフルパスや file:/// を
# Ubuntu on Windows のパスに変換する処理
__change_winpath2buwpath "$1"
# 指定されたパスがファイルならば、そのファイルのディレクトリを取得する
# dirname で変換する方法もあるけれど、外部コマンドは極力避けたいので
# シェル変数の展開で後方最短パターンの削除を利用する
if [ -f "$newpath" ]; then
echo "${newpath} is file."
newpath=${newpath%/*}
echo "remap to ${newpath}"
fi
\cd "$newpath"
fi
}
# cd コマンドを __cd に置換する
alias cd=__cd
そのうち追加する処理
入力値がディレクトリではなくファイルへのフルパスだった場合に、そのファイルが存在するディレクトリに対して cd できるようにすると、さらに便利なはず。
これは実際に cd する前に -d や -f でパスを検証し、必要に応じて入力値からファイル名部分を削るだけだからあっさり作れるハズ。
上記は実装済み。
参考資料
URLエンコードされた文字列をデコードする処理は下記ページの内容を参考にしました。
http://unix.stackexchange.com/questions/159253/decoding-url-encoding-percent-encoding