タイダログ

もっと怠けますか? (y/n)

ファイルの所有者を調べようとして手掛かりを消してしまった話

証拠は残っているよ。どんな時にもね。

第一発見者の供述

うちの学校、共有フォルダのルート直下に年度ごとのフォルダを作って、そこに各分掌や教科のファイルを置いているんですよ。バックアップが年度単位で取れて便利じゃないですか。

ところがルート直下にファイルやフォルダを作る人がいて、管理上、問題だと感じていたんですよね。

なので「移動させるか消してね。そしてここにはもう置かないでね」とアナウンスしつつ、ファイルの所有者を調べることにしたんです。もう、誰なのって思って……気になるじゃないですか。

そしたら、その……所有者は……私だって言われて……

興味深い事件だ。ネットワーク探偵が解決しよう。

話をまとめよう。以下の状態での運用を意図しているが、

Z:.
├─2017
├─2018
├─2019
├─2020
└─2021

ルート直下にファイルやフォルダを置いた者がいる。

Z:.
├─2017
├─2018
├─2019
├─2020
├─2021
├─一時保存フォルダ   ←これ
├─会議資料.docx     ←これ
├─作業用.xlsx       ←これ
└─分担表.docx       ←これ

ここに置くのは得策ではない。バックアップの対象から外れ、年度更新の意味がなくなる。現に最終更新日が2年前のファイルが残り続けているくらいだからね。

ファイルの所有者を見る

とりあえずファイルを別のディスクに移動させてから、落ち着いて所有者を見るとしよう。案ずることなかれ。手掛かりは現場に残されているものなのだよ。

code

Get-ChildItem -File | Get-Acl
Path         Owner         Access
----         -----         ------
会議資料.docx DESKTOP\taida BUILTIN\Administrators Allow  FullControl...
作業用.xlsx   DESKTOP\taida BUILTIN\Administrators Allow  FullControl...
分担表.docx   DESKTOP\taida BUILTIN\Administrators Allow  FullControl...

ふむ、奇妙だ。DESKTOP\taida というのは私のことである。ファイルの所有者として私の名前が出ている。私を犯人に仕立て上げるとは、なかなかやるじゃないか。

解決編

なぜ所有者が変わっているのか。ここで事件の流れを整理しよう。

  1. 第一発見者(私)が、ルート直下のファイル群を発見する
  2. 第一発見者が、当該ファイル群を別のディスクに移動させる。「ここにあっては邪魔だと思った」とのこと
  3. ファイルの所有者を見ると、所有者は第一発見者になっていた

謎が解けたぞ、ワトソン君。第一発見者がファイルを移動させたときに所有者が変わったのだ。事件現場のものを動かしてはいけないな。手掛かりは現場に残されているものなのだよ。現場保存は捜査の原則だ。

つまり、犯人は私だ。

それでも証拠は残っている

というわけで私が手掛かりを消したわけですが待ってください大丈夫ですまだ方法はあります。

ファイルを移動したことによって、ファイルのプロパティのうち「所有者」が変わってしまいましたが、「作成者」は変わっていないはずです。

Get-Acl コマンドレットではなく Shell.Application を使って確認しましょう。

code (2)

$path でファイルへのパスを、$pattern で取得するプロパティの名前を指定します。-match なので正規表現です。

作成者だけ見るなら $pattern = "^作成者$" とします。$pattern = "作成者" だと「共同作成者」などもヒットします。必要に応じて -like-eq などに変えてもいいです。

今回は所有者と作成者を見てみましょう。$pattern = "^(所有|作成)者$" です。

$path = "" # ファイルへのパス
$pattern = "^(所有|作成)者$"

$folderPath = Split-Path $path -Parent
$filePath = Split-Path $path -Leaf

$shell = New-Object -ComObject Shell.Application
$folder = $shell.NameSpace($folderPath)
$file = $folder.ParseName($filePath)

$indexRange = @(0..330)
$targetIndex = @($indexRange | Where-Object {$folder.GetDetailsOf($null, $_) -match $pattern})

$properties = @()
$targetIndex | ForEach-Object {$properties += [PSCustomObject]@{Index = $_; PropertyName = $folder.GetDetailsOf($null, $_); Property = $folder.GetDetailsOf($file, $_)}}

$properties

結果はこのような形で出ます。

Index PropertyName Property
----- ------------ --------
   10 所有者        DESKTOP\taida
   20 作成者        まじめ

ファイルを移動した際に「所有者」が私に変わりましたが、最初にこのファイルを作った真犯人もとい「作成者」が誰なのか分かりました。

function

Gist でどうぞ。

PowerShell module to get properties from files · GitHub

$path = "" # ファイルへのパス
$pattern = "^(所有|作成)者$"
Invoke-GetDetailsOf -Path $path -Pattern $pattern

対象ファイルが複数あるならこうです。

$pattern = "^(所有|作成)者$"
Get-ChildItem -File | ForEach-Object {Get-Item $_; Invoke-GetDetailsOf -Path $_ -Pattern $pattern | Format-Table}

ファイルのプロパティが変わる条件

以前どこかで見たのですが、見つからなかったのでまとめました。

操作 行き先 作成日時 更新日時 所有者 作成者
コピー 同一ドライブ 変化 変化なし 変化 変化なし
コピー 別ドライブ 変化 変化なし 変化 変化なし
コピー 別ネットワークドライブ 変化 変化なし 変化 変化なし
コピー リムーバブルディスク 変化 変化なし 変化 変化なし
移動 同一ドライブ 変化なし 変化なし 変化なし 変化なし
移動 別ドライブ 変化なし 変化なし 変化 変化なし
移動 別ネットワークドライブ 変化なし 変化なし 変化 変化なし
移動 リムーバブルディスク 変化なし 変化なし 変化 変化なし

事件を振り返って

この記事を書きながら気づきましたが、作成者はファイルを右クリックしてプロパティから見ることができます。ここまで話を大きくする必要はなかったのです。まあ、対象のファイルが10個とかあれば話は別ですけどね。

現場保存にせよ、右クリックのプロパティにせよ、「基本に立ち返る」ことを意識しようと思いました。

それとテキストファイルやPDF ファイル、フォルダなどには作成者プロパティはありません。その場合は現場保存が不可欠かと。