1

PowerShell スクリプトに取り組んでいますが、Compare-Objectコマンドレットが期待どおりの結果を返しません。スクリプト全体をここに記載することはしませんが、これが一般的な考え方です。

$knownFiles = Import-Csv -Path "C:\knownfiles.csv"
$currentFiles = Get-ChildItem -Path "\\file\share"
$knownFileObject = $knownFiles |
                   Select-Object -Property Name, Length, LastWriteTimeUTC |
                   Sort-Object -Property Name
$currentFileObject = $currentFiles |
                     Select-Object -Property Name, Length, LastWriteTimeUTC |
                     Sort-Object -Property Name

これで、一連のファイルの名前、長さ、および最終書き込み時刻を含む 2 つの並べ替えられた PSCustomObjects ができました。これが私が理解できないものです。

オブジェクトが同一である場合は、Compare-Object予想どおり何も返しません。ただし、以下の例を使用します。

$knownFileObject次のようになります。

名前の長さ LastWriteTimeUtc
---- ------ ----------------
file1.dat 38988 2018 年 1 月 1 日 8:04:57 午前
file2.dat 7182 2017 年 1 月 2 日 8:03:24 午前
file4.dat 1026 2017 年 1 月 3 日 8:04:20 午前
file5.dat 25137 2018 年 1 月 3 日 8:07:51 午前

$currentFileObject次のようになります。

名前の長さ LastWriteTimeUtc
---- ------ ----------------
file1.dat 38988 2018 年 1 月 1 日 8:04:57 午前
file2.dat 7182 2017 年 1 月 2 日 8:03:24 午前
file3.dat 1026 2018 年 1 月 2 日 8:04:30 午前
file4.dat 1026 2017 年 1 月 3 日 8:04:20 午前
file5.dat 25137 2018 年 1 月 3 日 8:07:51 午前

私が走れば

Compare-Object -ReferenceObject $knownFileObject -DifferenceObject $currentFileObject

これを返します:

InputObject SideIndicator
----------- -------------
@{Name=file5.dat; 長さ=25137; LastWriteTimeUtc=1/3/2018 8:07:51 AM} =>

2 つのオブジェクト間に違いがあることは確実に検出されますが、実際に異なるレコードではなく、常に最後の行だけが返されます。変更されたファイルが 2 つある場合は、最後の 2 行を返します。に を追加する"-property Name"Compare-Object、正しいファイル名が返されますが、サイズと書き込み時間の違いも探す必要があります。Export-Csv両方のオブジェクトをファイルに書き戻し、それらのファイルで実行Compare-ObjectすることができGet-Contentます。これはうまく機能しますが、このジョブは数百回実行されるため、2 つのファイルをディスクに書き込む必要はありません。異なるフォルダーでの 1 分あたりの回数。

編集:提案の 1 つに従って、私も試してみましCompare-Object ... -Property Name, Length, LastWriteTimeUtcた。それを行うと、両方のオブジェクトのすべてのアイテム、または 100% の不一致が返されます。

私は何を間違っていますか?

4

1 に答える 1

3

オブジェクトを比較するプロパティを指定します。

Compare-Object $knownFileObject $currentFileObject -Property Name, Length, LastWriteTimeUtc

また、同じものを比較していることを確認する必要があります。あなたのアプローチの問題は、オブジェクトのLastWriteTimeUtcプロパティがサブ秒の精度を持つオブジェクトであることです。FileInfoDateTime

PS C:\> Get-Date| フォーマットリスト *

DisplayHint : DateTime
DateTime : Donnerstag、2018 年 1 月 25 日 16:31:07
日付 : 25.01.2018 00:00:00
日 : 25
DayOfWeek : 木曜日
年の曜日: 25
時間 : 16
種類 : ローカル
ミリ秒:268 ←こちら
分 : 31
月 : 1
秒: 7
ティック : 636524946672682859
時刻: 16:31:07.2682859
年 : 2018

ただし、CSV のタイムスタンプは精度が秒単位に制限された文字列であるため、元のタイムスタンプと保存されたタイムスタンプの間にはわずかな違いがある可能性があります。

あなたの場合、タイムスタンプを定義された形式(たとえば、長いISO形式)で保存し、ディレクトリリストのタイムスタンプに同じ形式を使用するのが最善の方法です。ところで、配列の並べ替えは必要ないので、そのステップを削除できます。

$saved   = Import-Csv 'C:\knownfiles.csv' |
           Select-Object Name, Length, LastWriteTimeUtc
$current = Get-ChildItem '\\server\share' |
           Select-Object Name, Length,
               @{n='LastWriteTimeUtc';e={$_.LastWriteTimeUtc.ToString('s')}}

Compare-Object $saved $current -Property Name, Length, LastWriteTimeUtc
于 2018-01-24T22:37:54.593 に答える