PowerShell サンプルコード


# Multi-Format File Comparison Script
# SVG, Excel, SQL, JSON ファイルの差分比較と詳細出力

function Compare-JsonFiles {
    param(
        [string]$File1,
        [string]$File2
    )
    
    Write-Host "`n=== JSON比較: $([System.IO.Path]::GetFileName($File1)) vs $([System.IO.Path]::GetFileName($File2)) ===" -ForegroundColor Cyan
    
    try {
        $json1 = Get-Content $File1 -Raw | ConvertFrom-Json
        $json2 = Get-Content $File2 -Raw | ConvertFrom-Json
        
        $json1Str = $json1 | ConvertTo-Json -Depth 100 -Compress
        $json2Str = $json2 | ConvertTo-Json -Depth 100 -Compress
        
        if ($json1Str -eq $json2Str) {
            Write-Host "差分なし" -ForegroundColor Green
            return 0
        }
        
        # 行ごとの比較
        $lines1 = ($json1 | ConvertTo-Json -Depth 100) -split "`n"
        $lines2 = ($json2 | ConvertTo-Json -Depth 100) -split "`n"
        
        $maxLines = [Math]::Max($lines1.Length, $lines2.Length)
        $diffCount = 0
        
        for ($i = 0; $i -lt $maxLines; $i++) {
            $line1 = if ($i -lt $lines1.Length) { $lines1[$i].Trim() } else { "" }
            $line2 = if ($i -lt $lines2.Length) { $lines2[$i].Trim() } else { "" }
            
            if ($line1 -ne $line2) {
                $diffCount++
                Write-Host "行 $($i+1):" -ForegroundColor Yellow
                Write-Host "  File1: $line1" -ForegroundColor Red
                Write-Host "  File2: $line2" -ForegroundColor Green
            }
        }
        
        Write-Host "総差分行数: $diffCount" -ForegroundColor Magenta
        return $diffCount
    }
    catch {
        Write-Host "JSON解析エラー: $($_.Exception.Message)" -ForegroundColor Red
        return -1
    }
}

function Compare-XmlFiles {
    param(
        [string]$File1,
        [string]$File2
    )
    
    Write-Host "`n=== SVG/XML比較: $([System.IO.Path]::GetFileName($File1)) vs $([System.IO.Path]::GetFileName($File2)) ===" -ForegroundColor Cyan
    
    try {
        [xml]$xml1 = Get-Content $File1
        [xml]$xml2 = Get-Content $File2
        
        # 正規化されたXMLで比較
        $xml1Str = $xml1.OuterXml
        $xml2Str = $xml2.OuterXml
        
        if ($xml1Str -eq $xml2Str) {
            Write-Host "差分なし" -ForegroundColor Green
            return 0
        }
        
        # 行ごとの比較
        $lines1 = $xml1Str -split "`n"
        $lines2 = $xml2Str -split "`n"
        
        $maxLines = [Math]::Max($lines1.Length, $lines2.Length)
        $diffCount = 0
        
        for ($i = 0; $i -lt $maxLines; $i++) {
            $line1 = if ($i -lt $lines1.Length) { $lines1[$i].Trim() } else { "" }
            $line2 = if ($i -lt $lines2.Length) { $lines2[$i].Trim() } else { "" }
            
            if ($line1 -ne $line2) {
                $diffCount++
                Write-Host "行 $($i+1):" -ForegroundColor Yellow
                Write-Host "  File1: $line1" -ForegroundColor Red
                Write-Host "  File2: $line2" -ForegroundColor Green
            }
        }
        
        Write-Host "総差分行数: $diffCount" -ForegroundColor Magenta
        return $diffCount
    }
    catch {
        Write-Host "XML解析エラー: $($_.Exception.Message)" -ForegroundColor Red
        return -1
    }
}

function Compare-ExcelFiles {
    param(
        [string]$File1,
        [string]$File2
    )
    
    Write-Host "`n=== Excel比較: $([System.IO.Path]::GetFileName($File1)) vs $([System.IO.Path]::GetFileName($File2)) ===" -ForegroundColor Cyan
    
    try {
        # ImportExcelモジュールの確認
        if (-not (Get-Module -ListAvailable -Name ImportExcel)) {
            Write-Host "ImportExcelモジュールが必要です。インストール: Install-Module -Name ImportExcel" -ForegroundColor Red
            return -1
        }
        
        Import-Module ImportExcel
        
        $excel1 = Import-Excel $File1
        $excel2 = Import-Excel $File2
        
        if ($excel1.Count -ne $excel2.Count) {
            Write-Host "行数が異なります: File1($($excel1.Count)行) vs File2($($excel2.Count)行)" -ForegroundColor Yellow
        }
        
        $maxRows = [Math]::Max($excel1.Count, $excel2.Count)
        $diffCount = 0
        
        # 列名の取得
        $columns1 = if ($excel1.Count -gt 0) { $excel1[0].PSObject.Properties.Name } else { @() }
        $columns2 = if ($excel2.Count -gt 0) { $excel2[0].PSObject.Properties.Name } else { @() }
        $allColumns = ($columns1 + $columns2) | Sort-Object -Unique
        
        for ($i = 0; $i -lt $maxRows; $i++) {
            $row1 = if ($i -lt $excel1.Count) { $excel1[$i] } else { $null }
            $row2 = if ($i -lt $excel2.Count) { $excel2[$i] } else { $null }
            
            $rowDiff = $false
            foreach ($col in $allColumns) {
                $val1 = if ($row1) { $row1.$col } else { "" }
                $val2 = if ($row2) { $row2.$col } else { "" }
                
                if ($val1 -ne $val2) {
                    if (-not $rowDiff) {
                        Write-Host "行 $($i+1) に差分:" -ForegroundColor Yellow
                        $rowDiff = $true
                        $diffCount++
                    }
                    Write-Host "  列 '$col': '$val1' vs '$val2'" -ForegroundColor White
                }
            }
        }
        
        if ($diffCount -eq 0) {
            Write-Host "差分なし" -ForegroundColor Green
        } else {
            Write-Host "総差分行数: $diffCount" -ForegroundColor Magenta
        }
        
        return $diffCount
    }
    catch {
        Write-Host "Excel読み込みエラー: $($_.Exception.Message)" -ForegroundColor Red
        return -1
    }
}

function Compare-SqlFiles {
    param(
        [string]$File1,
        [string]$File2
    )
    
    Write-Host "`n=== SQL比較: $([System.IO.Path]::GetFileName($File1)) vs $([System.IO.Path]::GetFileName($File2)) ===" -ForegroundColor Cyan
    
    try {
        $sql1 = Get-Content $File1
        $sql2 = Get-Content $File2
        
        # 空行とコメント行を除外して比較
        $sql1Clean = $sql1 | Where-Object { $_ -notmatch '^\s*$' -and $_ -notmatch '^\s*--' } | ForEach-Object { $_.Trim() }
        $sql2Clean = $sql2 | Where-Object { $_ -notmatch '^\s*$' -and $_ -notmatch '^\s*--' } | ForEach-Object { $_.Trim() }
        
        $maxLines = [Math]::Max($sql1Clean.Length, $sql2Clean.Length)
        $diffCount = 0
        
        for ($i = 0; $i -lt $maxLines; $i++) {
            $line1 = if ($i -lt $sql1Clean.Length) { $sql1Clean[$i] } else { "" }
            $line2 = if ($i -lt $sql2Clean.Length) { $sql2Clean[$i] } else { "" }
            
            if ($line1 -ne $line2) {
                $diffCount++
                Write-Host "行 $($i+1):" -ForegroundColor Yellow
                Write-Host "  File1: $line1" -ForegroundColor Red
                Write-Host "  File2: $line2" -ForegroundColor Green
            }
        }
        
        if ($diffCount -eq 0) {
            Write-Host "差分なし" -ForegroundColor Green
        } else {
            Write-Host "総差分行数: $diffCount" -ForegroundColor Magenta
        }
        
        return $diffCount
    }
    catch {
        Write-Host "SQL読み込みエラー: $($_.Exception.Message)" -ForegroundColor Red
        return -1
    }
}

function Compare-TextFiles {
    param(
        [string]$File1,
        [string]$File2
    )
    
    Write-Host "`n=== テキスト比較: $([System.IO.Path]::GetFileName($File1)) vs $([System.IO.Path]::GetFileName($File2)) ===" -ForegroundColor Cyan
    
    try {
        $content1 = Get-Content $File1
        $content2 = Get-Content $File2
        
        $maxLines = [Math]::Max($content1.Length, $content2.Length)
        $diffCount = 0
        
        for ($i = 0; $i -lt $maxLines; $i++) {
            $line1 = if ($i -lt $content1.Length) { $content1[$i] } else { "" }
            $line2 = if ($i -lt $content2.Length) { $content2[$i] } else { "" }
            
            if ($line1 -ne $line2) {
                $diffCount++
                Write-Host "行 $($i+1):" -ForegroundColor Yellow
                Write-Host "  File1: $line1" -ForegroundColor Red
                Write-Host "  File2: $line2" -ForegroundColor Green
            }
        }
        
        if ($diffCount -eq 0) {
            Write-Host "差分なし" -ForegroundColor Green
        } else {
            Write-Host "総差分行数: $diffCount" -ForegroundColor Magenta
        }
        
        return $diffCount
    }
    catch {
        Write-Host "ファイル読み込みエラー: $($_.Exception.Message)" -ForegroundColor Red
        return -1
    }
}

function Compare-FilePair {
    param(
        [string]$File1,
        [string]$File2
    )
    
    if (-not (Test-Path $File1)) {
        Write-Host "ファイルが見つかりません: $File1" -ForegroundColor Red
        return -1
    }
    
    if (-not (Test-Path $File2)) {
        Write-Host "ファイルが見つかりません: $File2" -ForegroundColor Red
        return -1
    }
    
    $ext1 = [System.IO.Path]::GetExtension($File1).ToLower()
    $ext2 = [System.IO.Path]::GetExtension($File2).ToLower()
    
    if ($ext1 -ne $ext2) {
        Write-Host "異なる拡張子のファイルです: $ext1 vs $ext2" -ForegroundColor Yellow
    }
    
    switch ($ext1) {
        ".json" { return Compare-JsonFiles $File1 $File2 }
        ".svg" { return Compare-XmlFiles $File1 $File2 }
        ".xml" { return Compare-XmlFiles $File1 $File2 }
        ".xlsx" { return Compare-ExcelFiles $File1 $File2 }
        ".xls" { return Compare-ExcelFiles $File1 $File2 }
        ".sql" { return Compare-SqlFiles $File1 $File2 }
        default { return Compare-TextFiles $File1 $File2 }
    }
}

# メイン実行部分
function Main {
    param(
        [string]$Folder1,
        [string]$Folder2,
        [string]$OutputFile = ""
    )
    
    Write-Host "=== Multi-Format File Comparison ===" -ForegroundColor Green
    Write-Host "フォルダ1: $Folder1"
    Write-Host "フォルダ2: $Folder2"
    Write-Host ""
    
    if ($OutputFile) {
        Start-Transcript -Path $OutputFile
    }
    
    $extensions = @("*.json", "*.svg", "*.xlsx", "*.xls", "*.sql")
    $totalFiles = 0
    $totalDifferences = 0
    
    foreach ($ext in $extensions) {
        Write-Host "`n" + "="*50 -ForegroundColor Blue
        Write-Host "処理中: $ext ファイル" -ForegroundColor Blue
        Write-Host "="*50 -ForegroundColor Blue
        
        $files1 = Get-ChildItem -Path $Folder1 -Filter $ext -Recurse
        
        foreach ($file1 in $files1) {
            $relativePath = $file1.FullName.Substring($Folder1.Length + 1)
            $file2Path = Join-Path $Folder2 $relativePath
            
            if (Test-Path $file2Path) {
                $totalFiles++
                $diffCount = Compare-FilePair $file1.FullName $file2Path
                if ($diffCount -gt 0) {
                    $totalDifferences += $diffCount
                }
            } else {
                Write-Host "`n対応ファイルが見つかりません: $relativePath" -ForegroundColor Red
            }
        }
    }
    
    Write-Host "`n" + "="*60 -ForegroundColor Green
    Write-Host "=== 最終結果 ===" -ForegroundColor Green
    Write-Host "比較したファイル数: $totalFiles"
    Write-Host "総差分箇所数: $totalDifferences"
    Write-Host "="*60 -ForegroundColor Green
    
    if ($OutputFile) {
        Stop-Transcript
        Write-Host "`n結果がファイルに保存されました: $OutputFile"
    }
}

# 使用例とヘルプ
function Show-Help {
    Write-Host @"
=== Multi-Format File Comparison Script ===

使用方法:
1. 2つのファイルを比較:
   Compare-FilePair "C:\file1.json" "C:\file2.json"

2. 2つのフォルダを比較:
   Main "C:\folder1" "C:\folder2"

3. 結果をファイルに保存:
   Main "C:\folder1" "C:\folder2" "C:\diff_result.txt"

対応ファイル形式:
- JSON (.json)
- SVG/XML (.svg, .xml)
- Excel (.xlsx, .xls) ※ImportExcelモジュールが必要
- SQL (.sql)
- その他のテキストファイル

必要な準備:
Excel比較にはImportExcelモジュールをインストール:
Install-Module -Name ImportExcel -Force

"@ -ForegroundColor Cyan
}

# ヘルプ表示
Show-Help

# 実行例(コメントアウト)
# Main "C:\project\version1" "C:\project\version2" "C:\diff_results.txt"