TL; DR
次のようなコマンドで、動作します。
実行例
### 次のようなfrom.txtファイルとto.txtファイルがあった場合
cat .\from.txt
# This is from text.
# There is same line.
cat .\to.txt
# This is to text.
# There is same line.
### その2ファイルの中身の差分を見る
diff.ps1 .\from.txt .\to.txt
# Line U InputObject
# ---- - -----------
# 1 < This is from text.
# 1 > This is to text.
はじめに
下記記事の通り、WindowsのPowerShellにおけるdiffは、Linuxを使うときと同じイメージで使うとガッカリしてしまいます。
そこで、常にLinuxライクなdiffコマンドを実行するために、コマンドを自作します。
コマンドの用意
以下は、コマンドの完成までの道のりです。
差分を表示する
次のようなコマンドで、2ファイルの中身の差分を表示できます。
なお下記コマンドは、ファイル名の差分以外は上記参考記事の内容のままです。
from.txtとto.txtのファイルの中身の差分を表示するdiff.ps1
Compare-Object -ReferenceObject @(Get-Content -Path .\from.txt) -DifferenceObject @(Get-Content -Path .\to.txt) |
Sort-Object -Property @{Expression = {$_.InputObject.ReadCount}; Ascending = $true} |
Format-Table -Property @{Name = 'ReadCount'; Expression = {$_.InputObject.ReadCount}}, *
実行結果
diff.ps1
# ReadCount SideIndicator InputObject
# --------- ------------- -----------
# 1 <= This is from text.
# 1 => This is to text.
パラメーターを読込む
from.txtとto.txtといった固定ではなく、パラメーターとして差分を確認したいですよね。
パラメーターから読込んだファイルの中身の差分を確認するdiff.ps1
+ Param(
+ [parameter(mandatory=$true)][String]$DiffFileFrom,
+ [parameter(mandatory=$true)][String]$DiffFileTo
+ )
+
+ $DiffFileFromPath = Convert-Path $DiffFileFrom
+ $DiffFileToPath = Convert-Path $DiffFileTo
+
+ if ( $DiffFileFromPath -ne $null -and $DiffFileToPath -ne $null )
+ {
Compare-Object -ReferenceObject @(Get-Content -Path $DiffFileFromPath) -DifferenceObject @(Get-Content -Path $DiffFileToPath) |
Sort-Object -Property @{Expression = {$_.InputObject.ReadCount}; Ascending = $true} |
Format-Table -Property @{Name = 'ReadCount'; Expression = {$_.InputObject.ReadCount}}, *
+ }
実行結果
diff.ps1 .\from.txt .\to.txt
# ReadCount SideIndicator InputObject
# --------- ------------- -----------
# 1 <= This is from text.
# 1 => This is to text.
正確にはインデントを増やした Compare-Object
コマンド行も差分といえば差分なのですが、分かりやすさのため -w
しておきました。
表示形式を簡略化する
表示結果のスペースが広すぎるなと感じるので、少し短くしましょう。
表示結果を簡略化したdiff.ps1
Param(
[parameter(mandatory=$true)][String]$DiffFileFrom,
[parameter(mandatory=$true)][String]$DiffFileTo
)
$DiffFileFromPath = Convert-Path $DiffFileFrom
$DiffFileToPath = Convert-Path $DiffFileTo
if ( $DiffFileFromPath -ne $null -and $DiffFileToPath -ne $null )
{
Compare-Object -ReferenceObject @(Get-Content -Path $DiffFileFromPath) -DifferenceObject @(Get-Content -Path $DiffFileToPath) |
+ Select-Object @{
+ n='U';
+ e={ @{ '<=' = '<'; '=>' = '>' }[$_.SideIndicator] }
+ }, InputObject |
Sort-Object -Property @{Expression = {$_.InputObject.ReadCount}; Ascending = $true} |
- Format-Table -Property @{Name = 'ReadCount'; Expression = {$_.InputObject.ReadCount}}, *
+ Format-Table -Property @{Name = 'Line'; Expression = {$_.InputObject.ReadCount}}, *
}
実行結果
diff.ps1 .\from.txt .\to.txt
# Line U InputObject
# ---- - -----------
# 1 < This is from text.
# 1 > This is to text.
使い方をドキュメントに書く
使い方を書いて完成です。
diff.ps1
<#
.DESCRIPTION
The Linux-like diff command.
.EXAMPLE
PS C\:> diff.ps1 .\from.txt .\to.txt
#>
Param(
[parameter(mandatory=$true)][String]$DiffFileFrom,
[parameter(mandatory=$true)][String]$DiffFileTo
)
$DiffFileFromPath = Convert-Path $DiffFileFrom
$DiffFileToPath = Convert-Path $DiffFileTo
if ( $DiffFileFromPath -ne $null -and $DiffFileToPath -ne $null )
{
Compare-Object -ReferenceObject @(Get-Content -Path $DiffFileFromPath) -DifferenceObject @(Get-Content -Path $DiffFileToPath) |
Select-Object @{
n='U';
e={ @{ '<=' = '<'; '=>' = '>' }[$_.SideIndicator] }
}, InputObject |
Sort-Object -Property @{Expression = {$_.InputObject.ReadCount}; Ascending = $true} |
Format-Table -Property @{Name = 'Line'; Expression = {$_.InputObject.ReadCount}}, *
}
デジタル署名を実施する
PowerShellをコマンド化する際に必要なデジタル署名は、以下を参考にしてください。
これをしないと、スクリプトファイルがコマンド実行できません。
ちなみに、完成途中までのスクリプトファイルも、それぞれデジタル署名が必要です。
おわりに
デジタル署名、めっちゃ面倒ですね。