Word や Excel などの Office ファイルを開くと、“~$ファイル名.xlsx” といった “~$” から始まる名前の一時ファイルが作られます。通常はファイルを閉じるとこの一時ファイルは消えるのですが、外部のサーバに保存してあるファイルを開いた場合などに、一時ファイルが残ったままになることがあります。

これは、Office 2010 以降の「保護されたビュー」が標準で有効になっていることが影響しているようですが、これを無効にすると当然セキュリティが甘くなってしまいます。

今回、WebDAV 機能が使えるレンタルサーバを使って複数人でファイルを共有する案件があり、それぞれに WebDAV アカウンントを作成して、Windows エクスプローラーのネットワークの場所に各自の共有フォルダへのアクセスを設定してもらいました。

そして、運用してみると案の定上記の一時ファイルが残ったままになってしまいました。少しなら都度削除してもらうなどしてもらえばよいのですが、同じファイルを開くたびに “~$~$ファイル名.xlsx” のように一時ファイルが増えていき、非常に邪魔な存在になります。

Excel の一時ファイルが残ったフォルダのスクリーンショット

クライアントからも「何か解決法はないですかね?」といった相談を受けていたので、一時ファイルを一括削除するプログラムを PHP で作り、cron を使って定期的に実行するようにしてみました。

PHP で特定の複数のファイルを削除する方法は Web 上にいくつか紹介されており、一時ファイルを削除する場合は以下のような感じで実行できます。

$fileName = '/path/~$*.*';
foreach ( glob($fileName) as $val ) {
  unlink($val);
}

しかし今回は、管理者がアクセスできる最上位ディレクトリの中に各スタッフ用のディレクトリがあり、更に案件ごとにディレクトリが分けてあります。

上記コードの $filename のパス部分にワイルドカードを使ってみましたが、特定のディレクトリ階層のファイルしか削除されず、ディレクトリ配下を辿って処理する必要がありますが、このようなパターンはググってもなかなか見つかりません。

一方、ファイルとディレクトリを一括で削除する方法(ファイルが存在するディレクトリは rmdir() で削除できないので)はたくさん紹介されています。で、このファイルとディレクトリを一括で削除する記述を流用して、全ディレクトリ内の一時ファイルのみを削除するようにしました。

流用元は「PHP でディレクトリ以下を再帰的にファイル削除 – エンジニアきまぐれTips」で紹介されている記述です。ここでは、指定したディレクトリ以下を再帰的に辿って中身を抽出し、それがファイルなら unlink() で削除、ディレクトリなら rmdir() で削除という流れとなっていますが、この後半部分を書き替え、各アイテムのファイル名を取得して “~$” から始まっていれば unlink() で削除という具合にしてみました。

<?php
$path = './doc';

$items = new RecursiveIteratorIterator(
    new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::CURRENT_AS_SELF),
    RecursiveIteratorIterator::CHILD_FIRST
);

foreach ($items as $item) {
    $fileName = pathinfo($item->getPathname(), PATHINFO_BASENAME);
    if (preg_match('/^~$/', $fileName)) {
        unlink($item->getPathname());
    }
}
?>

これを delete_cashe.php としてサーバに置き、cron で毎日1回午前3時に実行するようにしました。日中のファイルを開いている時に一時ファイルを削除したら問題があるかもしれないので。これで、ファイルを開いた日のうちは一時ファイルが残りますが、翌日には削除されていることになります。

本当はこのようなファイル共有は Dropbox や Google Drive などのオンラインストレージサービスを使うのが簡単なんですが、今回はスタッフ一人ひとりにアカウントを取得してインストールしてもらうことがハードルでしたので、WebDAV を使うことにしました。結局、アクセス設定をしてもらったり、上手くいかない場合は WebDAV クライアントをインストールする必要があったりと、すんなりとは行かなかったのですが。