ファイルブラウザ(エクスプローラ)の右クリックメニューで、rclone・sshfs経由で閲覧しているssh先のファイル・フォルダをssh先のシェルやVS Codeで開く

sshを使ってリモートのサーバー上で開発を行っているとします。このとき、基本的にはほとんど全てのこと(コンパイル機械学習など計算を伴うものや、ファイル操作など)はsshで入った先のリモート上(ターミナル、あるいはVS CodeならRemote SSH拡張機能)で行えばいいのですが、ファイルの一覧・リネーム(移動)などはlsやmvを手打ちするよりも視覚的にわかりやすい手元のファイルマネージャーでやりたいという需要があります。

そこで使われるのがrclonesshfsなどのリモートのディレクトリをマウントしてくれるソフトウェアです。なおsshfsは開発終了になってしまったようなので現在はrcloneを使うのがいいと思います。rcloneのsshは独自の実装になっていてsshのconfigに書いてある内容を改めてrclone configの対話シェルで打ち込まなきゃいけないのが大変微妙(一方でsshfsはconfigを読んでくれる)だったのですが、2023年9月のv1.64.0から--sftp-sshというオプションが導入され、"dummy"みたいな名前のダミーのssh(sftp)設定を一つ作っておけばあとはrclone mount --sftp-ssh "ssh my_server" dummy:/ /media/myremoteみたいなコマンドで任意のsshサーバーがマウントできるようになり、いよいよsshfsを使う理由はなくなりました。

あと手元のLinux Mintで動かす限り、rclone mountするよりもrclone serve webdavしてからdav://localhost:8080にアクセスするやり方(gvfsというやつでマウントされるっぽい)のほうがレスポンスがいいような気がしますがこれは設定のしかたが悪いのかもしれません。

しかしマウント方法の細かい違いはここでは一旦置いておきます。とりあえず、マウントはできたとして、そこからがこの記事の対象です。ちなみにタイトルでわかると思いますがクライアントはWindows/Linuxどちらも対象です(持っていないので試していませんがMacでもできると思います)。サーバー側はとりあえず*nix想定です。

マウントまでできてもなお何が不満かというと、ファイルマネージャー(エクスプローラ)でファイルを閲覧したとして、そこから直接VS CodeのRemote SSHとかssh先のシェルを開く方法がないということです。ファイルの閲覧はせっかくできるのに、ssh先で同じものを操作しようと思ったらsshコマンドを手打ちしてlsで移動したりVS Codeの「最近使ったフォルダ」みたいなところを探さなきゃいけなかったりというのはバカバカしい感じがします。

幸い、エクスプローラはじめ多くのファイルマネージャーでは右クリックメニューに好き勝手なコマンドを入れることができます。これを使って、特定のパスに関しては、リモート先のパスに読み替えてコマンドを実行することにしてしまいましょう。

とりあえず、ここにコードの主要部分を上げておきました。

ge9/ssh-context-menu · GitHub

しかし、何せ右クリックメニューへの追加なので、レジストリをいじる必要があり、インストール/アンインストール用のコマンドとか書くのが面倒なのでそのへんは公開していません。各自で頑張って登録してください。この記事の伸び具合を見て整備しようと思います。

注意点をいくつか。Windows用のほうはPowerShellスクリプトなのでpowershell -ExecutionPolicy RemoteSigned -File "path\to\script.ps1"で呼び出せます。レジストリに関してはWindowsの右クリックメニューから複数ファイルをまとめて開く - Turgenev's Wikiも参考にしてください。なんのためかわからない置換処理は変な名前のフォルダへの対応策です。というかむしろここが一番価値のあるところかもしれません。これに関してはWindowsでエクスプローラーからフォルダを各種ターミナルで開く - Turgenev's Wikiにも書きました。

内容に関しても軽く解説します。

まず両者に共通して、設定ファイルにはローカルのフォルダ名とリモートのサーバー名・フォルダ名をペアで記載していて、上から順にマッチしていきます。なので適切に優先順位をつければ、C:\foo\bar\bazの中だったらserver1の/homeで開きたくて、そうじゃないけどC:\foo\barの中だったらserver2の/disk1で開きたくて、みたいなことも可能です。あとパスは単純に置換してるだけなので、ローカルのほうの末尾に(バック)スラッシュを書いたならリモートのほうにも書く、という感じで大丈夫です。テンプレートを付けているので、それをコピーして.txtに変えてから中身をいじるといいです。

シェルを開くほうはCygwinのターミナルを開くメニューと共用しています。どちらもWindows Terminalで開くように設定していて、この関係でセミコロンをバックスラッシュでエスケープする羽目になっています。

VS Codeのほうは、ファイル/フォルダを開くときにそれぞれ--file-uriと--folder-uriというオプションを指定する必要がある(自動判定に頼ると限界がある)ので、スクリプトの引数でvsc.ps1 folder C:\some\folderのようにタイプを指定できるようにしています。あとVS Codeのインストール時にパスを通すよう設定するとcode.cmdとかいう意味わからんファイルにはパスが通りますがCode.exeにパスが通りません。特殊文字を含んだパスの処理にcmd.exeを介在させるのは自爆行為なので、code.cmdが入っている親ディレクトリにあるCode.exeを直接呼び出しています。

あとremdelete.ps1というのがありますがこれはリモート先でrm -rfを実行するためのメニューを提供します。ローカルでやるとローカル側でファイルの再帰的な羅列と削除が走って非常に遅くなります。移動のときみたいにリモート側のコマンドに翻訳してくれればいいのに…。あと圧縮ファイルを解凍するメニューも入れようかなと思いましたがさすがにニッチすぎるのでやめました。このメニューに関しては手元ではレジストリキーのAppliedTo値にSystem.ItemPathDisplay:$<"\\"などと書くことで\\で始まるWebDAVサーバー内のフォルダのみこの右クリックメニューが表示されるようにしています。Windowsは意外と色々なことができて面白いですね。

Linuxは手元の環境としてはLinux Mintのcinnamonでgnome-terminalとNemoを使っています。gnome-terminalのかわりにここに置いてあるopen_gnome_terminal.shをデフォルトのターミナルとして登録する感じです。Nemoでは①フォルダの背景(白いところ)②フォルダの右クリック③(複数の、フォルダを含まない)ファイル、を対象にしたメニューをそれぞれ作れるのでこれを使ってメニューを追加しています。

ちなみに余談で、少し異なるものの関係あるツールとして、リモート先に接続したssh端末からコマンド一発でローカル側のVS CodeのRemote SSHを開けるようにしている方もいらっしゃるようです(VSCode Remote SSHで別Shellからファイルを開く)。

情報不足のところはあとから書き換えるつもりなので、わからないところがあれば気軽に聞いてください。