Google ドライブ と WSL フォルダ間でミラーリングをするバッチファイル

# 目的
Windows 環境にて Google ドライブの同期ツールをインストールしている環境では、Google ドライブにリンクするドライブレターが作成されます。

https://support.google.com/a/users/answer/13022292?hl=ja

このドライブレターをWSLにマウントさせたい場合は、下記コマンドにて実行することが出来ます。
>　$ sudo mount -t drvfs G: /mnt/g

 - `drvfs G:` にはGoogle ドライブが割り当てられたWindowsから見たドライブレターを指定
 - `/mnt/g` にはあらかじめマウントさせたいディレクトリを作成しておきます

しかし私の環境においては、上記手順でマウントしたフォルダでのWSL操作がいまいち安定しなかったので、`robocopy` コマンドを使ったバッチファイルを作成して、Linux環境フォルダへファイルをミラーリングする方法を調査しました。

# ミラーリングを実行するためのバッチファイル

`robocopy` コマンドを実行するバッチファイルを作成し、バッチを実行したフォルダをソースにして、もう片方のフォルダへミラーリングを実行します。
よって、Google ドライブ側から実行した場合は、WSLフォルダへミラーして、WSL側から実行した場合は、Google ドライブへミラーが行われます。

``` mirroring.bat
@echo off
setlocal enabledelayedexpansion
chcp 65001

set "SCRIPT_PATH=%~dp0"
set "SCRIPT_PATH=%SCRIPT_PATH:~0,-1%"

pushd "%SCRIPT_PATH%"
cd

set "exclude_list="
for /f "delims=" %%A in (.exclude_list.txt) do (
	set "exclude_list=!exclude_list! %%A"
)

set "GDRIVE="
set "PSC_GetLetter=Get-WmiObject -Class Win32_Volume | Where-Object {$_.Label -like '*Google*' -or $_.FileSystem -like '*GVFS*'} | Select-Object -ExpandProperty DriveLetter"
for /f "usebackq delims=" %%A in (`powershell -NoProfile -ExecutionPolicy Bypass -Command "%PSC_GetLetter%"`) do (
	set "GDRIVE=%%A"
)

set "GDRIVE_PATH=%GDRIVE%\マイドライブ\<GoogleDriveのフォルダ>"
set "WSL_PATH=\\wsl.localhost\<ディストリビューション>\<WSLのフォルダ>"

echo "%SCRIPT_PATH%" | findstr /C:"wsl.localhost" >nul
if %errorlevel%==0 (
	goto WSL_SOURCE
) else (
	goto GDRIVE_SOURCE
)

:WSL_SOURCE
robocopy /MIR /R:0 "%SCRIPT_PATH%" "%GDRIVE_PATH%" /XF %exclude_list% /UNILOG:NUL /TEE
goto END

:GDRIVE_SOURCE
robocopy /MIR /R:0 "%SCRIPT_PATH%" "%WSL_PATH%" /XF %exclude_list% /UNILOG:NUL /TEE
goto END

:END
popd
pause
```

## バッチファイルの解説

UTF-8 のコードテーブルでバッチを実行するための準備。
``` bat:
@echo off
setlocal enabledelayedexpansion
chcp 65001
```

開始したバッチファイルの格納フォルダを取得。
`%~dp0` のままだと、末尾のバックスラッシュ(\\)が `robocopy` コマンドに悪さするので取り除きます。
``` bat:
set "SCRIPT_PATH=%~dp0"
set "SCRIPT_PATH=%SCRIPT_PATH:~0,-1%"
```

WSL側からバッチを実行すると、CMDがUNCパスをサポート出来ないので、`pushd` でドライブレターを設定します。
``` bat:
pushd "%SCRIPT_PATH%"
cd
```

バッチと同じフォルダにミラーリングを除外するファイル名のリストをテキストで保存して、それらを読み込みます。
``` bat:
set "exclude_list="
for /f "delims=" %%A in (.exclude_list.txt) do (
	set "exclude_list=!exclude_list! %%A"
)
```

Google ドキュメント系のファイルはコピーできないので、これらの拡張子を除外リストに登録しました。
``` .exclude_list.txt
*.gdoc
*.gsheet
*.gslides
```

Google ドライブのドライブレターをPowerShellコマンドを用いて取得します。
ここは、私の複数のWindows環境によってGoogleドライブがマウントされたドライブレターが異なっているため実装しています。
``` bat:
set "GDRIVE="
set "PSC_GetLetter=Get-WmiObject -Class Win32_Volume | Where-Object {$_.Label -like '*Google*' -or $_.FileSystem -like '*GVFS*'} | Select-Object -ExpandProperty DriveLetter"
for /f "usebackq delims=" %%A in (`powershell -NoProfile -ExecutionPolicy Bypass -Command "%PSC_GetLetter%"`) do (
	set "GDRIVE=%%A"
)
```
:::note warn
上記PowerShellコマンドは Gemini に質問して作成していますが、下記のように互換性には注意が必要なようです。
> これらの方法は、Googleドライブの同期クライアントの内部実装に依存するため、将来のアップデートによって動作しなくなる可能性があります。
:::

Google ドライブ、WSL のそれぞれミラーリングさせたいフォルダパスを作成。
``` bat:
set "GDRIVE_PATH=%GDRIVE%\マイドライブ\<GoogleDriveのフォルダ>"
set "WSL_PATH=\\wsl.localhost\<ディストリビューション>\<WSLのフォルダ>"
```

バッチのパスからミラーリングのソースを判定して、ラベルにジャンプします。

``` bat:
echo "%SCRIPT_PATH%" | findstr /C:"wsl.localhost" >nul
if %errorlevel%==0 (
	goto WSL_SOURCE
) else (
	goto GDRIVE_SOURCE
)
```

`robocopy` コマンドを用いて、フォルダーをミラーリングします。
`/UNILOG:NUL /TEE` オプションはUTF-8環境で全角文字を化けさせないためのおまじないです。
``` bat:
:WSL_SOURCE
robocopy /MIR /R:0 "%SCRIPT_PATH%" "%GDRIVE_PATH%" /XF %exclude_list% /UNILOG:NUL /TEE
goto END

:GDRIVE_SOURCE
robocopy /MIR /R:0 "%SCRIPT_PATH%" "%WSL_PATH%" /XF %exclude_list% /UNILOG:NUL /TEE
goto END
```

`popd` で最初にマウントしたドライブレターを削除して、バッチを終了します。
``` bat:
:END
popd
pause
```