PowerShell にも diff がある?
あるにはありますが、初心者なかせです。わたしははまりました。
たとえばつぎのふたつのテキスト ファイルで PS でも diff ってみますと、個人的には残念な結果をえます。
PS> cat .\poem.txt
Great fleas have little fleas
upon their backs to bite 'em,
And little fleas have lesser fleas,
and so ad infinitum.
And the great fleas themselves, in turn,
have greater fleas to go on;
While these again have greater still,
and greater still, and so on.
PS> cat .\new_poem.txt
Great fleas have little fleas
upon their backs to bite them,
And little fleas have lesser fleas,
and so on ad infinitum.
And the great fleas themselves, in turn,
have greater fleas to go on;
While these again have greater still,
and greater still, and so on.
PS> diff .\poem.txt .\new_poem.txt
InputObject SideIndicator
----------- -------------
.\new_poem.txt =>
.\poem.txt <=
UNIX 系ならつぎのような出力がえられるところ。
$ diff poem.txt new_poem.txt
2c2
< upon their backs to bite 'em,
---
> upon their backs to bite them,
4c4
< and so ad infinitum.
---
> and so on ad infinitum.
PS の diff は Compare-Object の alias
-
Get-Alias -Name diffとするとdiff -> Compare-Objectとでます。 - 逆に
Get-Alias -Definition Compare-Objectとするとデフォルトでcompareとdiffとがでます。
Compare-Object の構文は
PS> Get-Command -Name Compare-Object -Syntax
Compare-Object [-ReferenceObject] <psobject[]> [-DifferenceObject] <psobject[]> [-SyncWindow <int>] [-Property <Object[]>] [-ExcludeDifferent] [-IncludeEqual] [-PassThru] [-Culture <string>] [-CaseSensitive] [<CommonParameters>]
すなわち .\poem.txt と .\new_poem.txt をそれぞれ単に psobject (を継承する string) の要素数 1 の配列としてうけとった模様です。
というわけで、ファイルの内容を Get しないとなりません。いろいろ略さずにかくと1
PS> Compare-Object -ReferenceObject @(Get-Content -Path .\poem.txt) -DifferenceObject @(Get-Content -Path .\new_poem.txt)
InputObject SideIndicator
----------- -------------
upon their backs to bite them, =>
and so on ad infinitum. =>
upon their backs to bite 'em, <=
and so ad infinitum. <=
行番号をうるには
しかし、まだ不満です。
- 行番号が表示されない。
- 対応する行が隣接していない。
Get-Content -Path .\poem.txt | Get-Member してみると ReadCount という NoteProperty がありますが、これは Compare-Object の結果の InputObject に温存されています。このことを利用してようやくのぞましい結果をえられたのでした。
PS> Compare-Object -ReferenceObject @(Get-Content -Path .\poem.txt) -DifferenceObject @(Get-Content -Path .\new_poem.txt) | Select-Object -Property @{Name = 'ReadCount'; Expression = {$_.InputObject.ReadCount}}, * | Sort-Object -Property ReadCount
ReadCount InputObject SideIndicator
--------- ----------- -------------
2 upon their backs to bite 'em, <=
2 upon their backs to bite them, =>
4 and so ad infinitum. <=
4 and so on ad infinitum. =>
2020/04/17 追記
上記 Select-Object ではあたらしいオブジェクトを生成しています2。
Sorting Objects | Using hash tables をよみかえしていてきづいたのですが、ハッシュ テーブルをつかえばふかいところにあるプロパティでもソートできますと。あとは表示のときに ReadCount をおもてにもってくるのでよければ Format-Table にまかせて
Compare-Object -ReferenceObject @(Get-Content -Path .\poem.txt) -DifferenceObject @(Get-Content -Path .\new_poem.txt) |
Sort-Object -Property @{Expression = {$_.InputObject.ReadCount}; Ascending = $true} |
Format-Table -Property @{Name = 'ReadCount'; Expression = {$_.InputObject.ReadCount}}, *
ただ、ながい。常用するようなら function でくるむところでしょうか。