Windowsのバックアップ機能で、PCのバックアップを外付けのUSBディスク(Bドライブ)に取っていた。ただ、バックアップがそのディスク1台にしかないのが気になったので、PCに内蔵しているほとんど使っていないHDD(Gドライブ)に、robocopyでバックアップのコピーを取ることにした。
ところが、robocopyのログを見るとコピーは終わっているのに、コピー先のG:\Bドライブフォルダがエクスプローラーに表示されない。
結論から書くと、ドライブのルート(B:\)をコピー元にすると、コピー先のフォルダに「隠し」と「システム」の属性が付くのが原因だった。robocopyの後にattrib -s -hで属性を外せば表示される。あわせて、このバッチを「管理者として実行」しないと動かなかった理由も、当時のログから分かったので書いておく。
原因:ドライブのルートには隠し属性とシステム属性が付いている
Microsoftのrobocopyのドキュメントにも、次のように書かれている。
デバイスの ルート からデータがコピーされた場合、コピー先ディレクトリはコピープロセス中に「hidden」属性と「system」属性を採用します。
NTFSのドライブのルートには、もともと隠し属性とシステム属性が付いている。robocopyはフォルダの属性もコピーする(/DCOPYの既定値はDAで、Aが属性)ので、コピー先のフォルダも隠しフォルダ・システムフォルダになる。エクスプローラーは初期設定ではこの2つの属性が付いたフォルダを表示しないので、フォルダが消えたように見える。中身はちゃんとコピーされていて、アドレスバーにパスを直接入力すれば開ける。
私はこの現象をRobocopyでコピー先フォルダが非表示になる - n-Archives.netで知った。
直し方:attribで隠し属性とシステム属性を外す
コピー先のフォルダに対して、次のコマンドを実行する。
attrib -s -h "G:\Bドライブ"
-sがシステム属性、-hが隠し属性を外すオプションだ。Microsoftのattribのドキュメントにあるとおり、システム属性や隠し属性が付いていると、ほかの属性を変える前にそれを外す必要があるので、-sと-hは必ず一緒に指定する。
robocopyを実行するたびにまた属性が付くので、私はバッチファイルの中でrobocopyの直後にattribを実行するようにした。
実際に使っているバッチファイル
今使っているバッチファイルがこれだ(ログの保存先のNAS名だけ<NAS>に置き換えている)。
set srcfolder="B:" set dstfolder="G:\Bドライブ" set logfolder="\\<NAS>\backup\バックアップ用ツール\BtoGドライブロボコピー\log" set logfile=%logfolder%\%date:~0,4%-%date:~5,2%-%date:~8,2%_datacopy.log robocopy "%srcfolder%" "%dstfolder%" /MIR /DCOPY:DAT /COPYALL /IT /B /log+:"%logfile%" /np /R:3 /W:3 attrib -s -h "%dstfolder%" forfiles /P "%logfolder%" /M "*.log" /D -93 /C "cmd /c del @file"
やっていることは次の3つだ。
- 7行目:BドライブをGドライブの「Bドライブ」フォルダにミラーリングする(
/MIRはコピー元にないファイルをコピー先から消すので、コピー先のフォルダを間違えないこと) - 8行目:コピー先フォルダの隠し属性とシステム属性を外す
- 9行目:93日より古いログを消す
ログのファイル名に使っている%date:~0,4%などは、日付が2024/01/04の形で表示される環境を前提にしている。
ちなみに、ローカルのフォルダをNASにバックアップするPowerShell版のスクリプトは、RobocopyでローカルフォルダのデータをID/パスワード付きのNASにバックアップするに書いた。
管理者として実行しないと動かなかった理由
このバッチは、ダブルクリックで普通に実行するとうまくいかなかったので、「管理者として実行」にチェックを入れたショートカットを作って、そこから実行している。

ショートカットのプロパティの「ショートカット」タブで「詳細設定」を押し、「管理者として実行」にチェックを入れると、ダブルクリックするだけで管理者として実行されるようになる(実行のたびにユーザーアカウント制御の確認は出る)。
なぜ管理者権限が必要だったのか、理由はもう覚えていなかった。今回、当時のログを見返すと、2024年1月4日の実行で次のエラーが出て、コピーが始まる前に止まっていた(その30秒ほど後の実行は、最後まで終わっていた)。
エラー: 監査管理のユーザー権利がありません。
原因は、バッチに付けていた/COPYALLだ。Microsoftのドキュメントによると、/COPYALLは/COPY:DATSOUと同じで、最後のUは「監査情報」のコピーを表す。監査情報を扱うには「監査とセキュリティ ログの管理」(SeSecurityPrivilege)というユーザー権利が必要で、この権利は既定ではAdministratorsグループにしか与えられていない。
また、/B(バックアップモード)は、ファイルやフォルダのアクセス許可を無視してコピーするモードだ。こちらで使う「ファイルとディレクトリのバックアップ」(SeBackupPrivilege)の権利も、既定ではAdministratorsとBackup Operatorsにしか与えられていない。
管理者のアカウントでサインインしていても、「管理者として実行」しないプログラムはこれらの権利を使えない。管理者として実行しないとうまくいかなかったのは、これが理由だと考えられる。
なお、/COPYALLを/COPY:DAT(データ・属性・タイムスタンプだけ)にすれば、監査情報の権利は不要になる。ただ、/Bも外すと、アクセス許可で読めないファイルがコピーできなくなる可能性がある。私はこの組み合わせを試していないので、変える場合は/L(一覧だけ表示してコピーしない)で動きを確かめてからにしてほしい。
まとめ
- robocopyでドライブのルート(
B:\など)をコピーすると、コピー先フォルダに隠し属性とシステム属性が付いて、エクスプローラーに表示されなくなる - robocopyの後に
attrib -s -h "コピー先フォルダ"を実行すれば表示される。バッチに入れておくと毎回直せる /COPYALL(監査情報のコピー)や/B(バックアップモード)を使うと、管理者として実行しないと動かない。ショートカットの「管理者として実行」を使うと楽

コメント