【完全版】PowerShell Add-Contentコマンドの使い方|ファイル追記操作を完全マスター

Windows

PowerShellでファイル操作を行う際、こんなニーズに直面することがよくあります:

「既存のログファイルに新しい記録を追加したい」
「設定ファイルに項目を追記したい」
「複数のファイルの内容を統合したい」

このような場面で活躍するのがAdd-Contentコマンドレットです。

この記事では、PowerShell初心者から中級者まで役立つ、Add-Contentの基本から応用までを実例とともに詳しく解説します。

スポンサーリンク

Add-Contentとは?

基本概念

Add-Contentは、PowerShellで既存のファイルにテキストやデータを追記するためのコマンドレットです。

ファイルの末尾に新しい内容を追加し、元の内容はそのまま保持されます。

基本構文

Add-Content
   [-Path] <string[]>
   [-Value] <Object[]>
   [-PassThru]
   [-Filter <string>]
   [-Include <string[]>]
   [-Exclude <string[]>]
   [-Force]
   [-Credential <pscredential>]
   [-WhatIf]
   [-Confirm]
   [-NoNewline]
   [-Encoding <Encoding>]
   [-AsByteStream]
   [-Stream <string>]
   [<CommonParameters>]

最もシンプルな使用例:

Add-Content -Path "C:\log\app.log" -Value "処理が完了しました"

主要なパラメーター

パラメーター説明必須
-Path追記先のファイルパス
-Value追記する内容
-Encoding文字エンコーディング
-Force読み取り専用ファイルにも追記
-NoNewline末尾の改行を追加しない
-WhatIf実行せずに結果を予測表示

基本的な使い方

単一行の追記

# 基本的な文字列の追記
Add-Content -Path "C:\temp\sample.txt" -Value "Hello World"

# 変数を使った追記
$message = "PowerShellで追記しました"
Add-Content -Path "C:\temp\sample.txt" -Value $message

# 現在の日時を追記
Add-Content -Path "C:\temp\sample.txt" -Value (Get-Date)

複数行の追記

# 配列を使った複数行追記
$lines = @(
    "第1行目",
    "第2行目", 
    "第3行目"
)
Add-Content -Path "C:\temp\sample.txt" -Value $lines

# ヒアストリングを使った複数行追記
$multilineText = @"
これは複数行の
テキストです。
まとめて追記できます。
"@
Add-Content -Path "C:\temp\sample.txt" -Value $multilineText

パイプラインとの組み合わせ

# パイプラインから値を受け取って追記
"行1", "行2", "行3" | Add-Content -Path "C:\temp\sample.txt"

# Get-Contentと組み合わせてファイル統合
Get-Content "source1.txt" | Add-Content -Path "combined.txt"
Get-Content "source2.txt" | Add-Content -Path "combined.txt"

実践的な使用例

ログファイルの管理

日時付きログの追記:

function Write-Log {
    param(
        [string]$Message,
        [string]$LogPath = "C:\logs\application.log",
        [string]$Level = "INFO"
    )
    
    $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
    $logEntry = "[$timestamp] [$Level] $Message"
    Add-Content -Path $LogPath -Value $logEntry
}

# 使用例
Write-Log -Message "アプリケーションが開始されました"
Write-Log -Message "エラーが発生しました" -Level "ERROR"

ローテーション機能付きログ:

function Write-RotatingLog {
    param(
        [string]$Message,
        [string]$LogPath = "C:\logs\app.log",
        [int]$MaxSizeMB = 10
    )
    
    # ファイルサイズをチェック
    if (Test-Path $LogPath) {
        $fileSize = (Get-Item $LogPath).Length / 1MB
        if ($fileSize -gt $MaxSizeMB) {
            $backupPath = $LogPath.Replace(".log", "_$(Get-Date -Format 'yyyyMMdd_HHmmss').log")
            Move-Item $LogPath $backupPath
        }
    }
    
    $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
    Add-Content -Path $LogPath -Value "[$timestamp] $Message"
}

CSVファイルの操作

# CSVヘッダーの作成
$csvHeader = "名前,年齢,部署"
Add-Content -Path "C:\data\employees.csv" -Value $csvHeader

# データの追記
$newEmployee = "田中太郎,30,営業部"
Add-Content -Path "C:\data\employees.csv" -Value $newEmployee

# オブジェクトからCSV形式で追記
$employee = [PSCustomObject]@{
    Name = "佐藤花子"
    Age = 28
    Department = "技術部"
}
$csvLine = "$($employee.Name),$($employee.Age),$($employee.Department)"
Add-Content -Path "C:\data\employees.csv" -Value $csvLine

設定ファイルの管理

# INI形式の設定ファイルに追記
function Add-ConfigEntry {
    param(
        [string]$ConfigPath,
        [string]$Section,
        [string]$Key,
        [string]$Value
    )
    
    $configEntry = if ($Section) {
        "[$Section]`n$Key=$Value"
    } else {
        "$Key=$Value"
    }
    
    Add-Content -Path $ConfigPath -Value $configEntry
}

# 使用例
Add-ConfigEntry -ConfigPath "C:\config\app.ini" -Section "Database" -Key "Server" -Value "localhost"

レポート生成

# システム情報レポートの作成
$reportPath = "C:\reports\system_report_$(Get-Date -Format 'yyyyMMdd').txt"

# レポートヘッダー
Add-Content -Path $reportPath -Value "=== システムレポート ==="
Add-Content -Path $reportPath -Value "生成日時: $(Get-Date)"
Add-Content -Path $reportPath -Value ""

# システム情報の追記
Add-Content -Path $reportPath -Value "=== コンピューター情報 ==="
Get-ComputerInfo | Select-Object WindowsProductName, TotalPhysicalMemory | 
    ForEach-Object { Add-Content -Path $reportPath -Value $_.ToString() }

# プロセス情報の追記
Add-Content -Path $reportPath -Value "`n=== 上位プロセス(CPU使用率順) ==="
Get-Process | Sort-Object CPU -Descending | Select-Object -First 10 Name, CPU |
    ForEach-Object { Add-Content -Path $reportPath -Value "$($_.Name): $($_.CPU)" }

エンコーディングの管理

PowerShell 5.1での文字化け対策

# UTF-8エンコーディングで追記(PowerShell 5.1)
$utf8 = New-Object System.Text.UTF8Encoding $false
Add-Content -Path "file.txt" -Value "日本語テキスト" -Encoding UTF8

# Shift-JISエンコーディングで追記
Add-Content -Path "file.txt" -Value "日本語テキスト" -Encoding Default

PowerShell 7以降の改善されたエンコーディング

# PowerShell 7では自動的にUTF-8が使用される
Add-Content -Path "file.txt" -Value "日本語テキスト"

# 明示的なエンコーディング指定
Add-Content -Path "file.txt" -Value "日本語テキスト" -Encoding utf8BOM
Add-Content -Path "file.txt" -Value "日本語テキスト" -Encoding utf8NoBOM

エラー処理とTips

ファイル存在チェック

# ファイルが存在しない場合の処理
$filePath = "C:\logs\app.log"

if (-not (Test-Path $filePath)) {
    # ディレクトリも含めて確実に作成
    $directory = Split-Path $filePath -Parent
    if (-not (Test-Path $directory)) {
        New-Item -Path $directory -ItemType Directory -Force
    }
    # 空のファイルを作成
    New-Item -Path $filePath -ItemType File -Force
}

Add-Content -Path $filePath -Value "ログエントリ"

Try-Catchを使用したエラーハンドリング

function Safe-AddContent {
    param(
        [string]$Path,
        [string]$Value
    )
    
    try {
        Add-Content -Path $Path -Value $Value -ErrorAction Stop
        Write-Host "正常に追記されました: $Path" -ForegroundColor Green
    }
    catch [System.UnauthorizedAccessException] {
        Write-Error "アクセス権限がありません: $Path"
    }
    catch [System.IO.DirectoryNotFoundException] {
        Write-Error "ディレクトリが見つかりません: $Path"
    }
    catch {
        Write-Error "予期しないエラーが発生しました: $($_.Exception.Message)"
    }
}

# 使用例
Safe-AddContent -Path "C:\protected\file.txt" -Value "テストデータ"

大量データの効率的な処理

# 大量のデータを効率的に処理
function Add-BulkContent {
    param(
        [string]$Path,
        [string[]]$Data,
        [int]$BatchSize = 1000
    )
    
    for ($i = 0; $i -lt $Data.Count; $i += $BatchSize) {
        $batch = $Data[$i..([Math]::Min($i + $BatchSize - 1, $Data.Count - 1))]
        Add-Content -Path $Path -Value $batch
        Write-Progress -Activity "データ書き込み中" -PercentComplete (($i / $Data.Count) * 100)
    }
    Write-Progress -Activity "データ書き込み中" -Completed
}

関連コマンドレットとの使い分け

Add-Content vs Set-Content

コマンドレット動作使用場面
Add-Contentファイルに追記ログ記録、データ蓄積
Set-Contentファイルを上書き設定ファイルの更新、新規作成
# Add-Content: 既存内容を保持して追記
Add-Content -Path "log.txt" -Value "新しいログ"

# Set-Content: 既存内容を削除して新規作成
Set-Content -Path "config.txt" -Value "新しい設定"

Add-Content vs Out-File

# Add-Content: シンプルな追記
Add-Content -Path "file.txt" -Value "追記内容"

# Out-File: オブジェクトの書式化出力(追記モード)
Get-Process | Out-File -FilePath "processes.txt" -Append

# Out-File: 幅を指定して出力
Get-Service | Out-File -FilePath "services.txt" -Append -Width 200

Export-Csvとの使い分け

# CSV形式でオブジェクトを追記する場合
$data = @(
    [PSCustomObject]@{Name="田中"; Age=30},
    [PSCustomObject]@{Name="佐藤"; Age=25}
)

# Export-Csv(ヘッダー付き、既存ファイルに追記)
$data | Export-Csv -Path "data.csv" -Append -NoTypeInformation -Encoding UTF8

# Add-Content(手動でCSV形式を作成)
$data | ForEach-Object { 
    Add-Content -Path "data.csv" -Value "$($_.Name),$($_.Age)" 
}

高度な使用例

条件付き追記

# 特定の条件でのみ追記
$errorLevel = "WARNING"
$logPath = "C:\logs\app.log"

# エラーレベルによって異なる処理
switch ($errorLevel) {
    "INFO" { 
        Add-Content -Path $logPath -Value "[INFO] $(Get-Date): 情報メッセージ"
    }
    "WARNING" { 
        Add-Content -Path $logPath -Value "[WARNING] $(Get-Date): 警告メッセージ"
        # 警告の場合は別ファイルにも記録
        Add-Content -Path "C:\logs\warnings.log" -Value "[WARNING] $(Get-Date): 警告メッセージ"
    }
    "ERROR" { 
        Add-Content -Path $logPath -Value "[ERROR] $(Get-Date): エラーメッセージ"
        # エラーの場合はイベントログにも記録
        Write-EventLog -LogName Application -Source "MyApp" -EventId 1001 -Message "エラーが発生しました"
    }
}

テンプレート機能

function Add-TemplatedContent {
    param(
        [string]$TemplatePath,
        [string]$OutputPath,
        [hashtable]$Replacements
    )
    
    $template = Get-Content -Path $TemplatePath -Raw
    
    foreach ($key in $Replacements.Keys) {
        $template = $template -replace "\{\{$key\}\}", $Replacements[$key]
    }
    
    Add-Content -Path $OutputPath -Value $template
}

# テンプレートファイル(template.txt)の内容例:
# こんにちは、{{Name}}さん
# 今日は{{Date}}です。
# {{Message}}

# 使用例
$replacements = @{
    "Name" = "田中"
    "Date" = (Get-Date -Format "yyyy年MM月dd日")
    "Message" = "PowerShellの学習をがんばりましょう!"
}

Add-TemplatedContent -TemplatePath "template.txt" -OutputPath "output.txt" -Replacements $replacements

並行処理での安全な追記

# ファイルロックを考慮した安全な追記
function Add-ContentSafe {
    param(
        [string]$Path,
        [string]$Value,
        [int]$RetryCount = 3,
        [int]$RetryDelayMs = 100
    )
    
    for ($i = 0; $i -lt $RetryCount; $i++) {
        try {
            Add-Content -Path $Path -Value $Value -ErrorAction Stop
            return $true
        }
        catch [System.IO.IOException] {
            if ($i -eq ($RetryCount - 1)) {
                throw "ファイルへの書き込みに失敗しました: $Path"
            }
            Start-Sleep -Milliseconds $RetryDelayMs
        }
    }
    return $false
}

パフォーマンスの最適化

バッチ処理による高速化

# 非効率な方法(1行ずつ追記)
$data = 1..10000
Measure-Command {
    foreach ($item in $data) {
        Add-Content -Path "slow.txt" -Value "Item: $item"
    }
}

# 効率的な方法(まとめて追記)
Measure-Command {
    $lines = foreach ($item in $data) { "Item: $item" }
    Add-Content -Path "fast.txt" -Value $lines
}

StringBuilder を使用した大量データ処理

# 大量のデータを効率的に処理
function Add-LargeContent {
    param(
        [string]$Path,
        [array]$Data
    )
    
    $stringBuilder = New-Object System.Text.StringBuilder
    
    foreach ($item in $Data) {
        [void]$stringBuilder.AppendLine($item)
    }
    
    Add-Content -Path $Path -Value $stringBuilder.ToString()
}

トラブルシューティング(よくある問題と解決策)

文字化けが発生する

# 問題のあるコード
Add-Content -Path "file.txt" -Value "日本語"

# 解決策
Add-Content -Path "file.txt" -Value "日本語" -Encoding UTF8

ファイルが読み取り専用でエラーになる

# エラーが発生するコード
Add-Content -Path "readonly.txt" -Value "テスト"

# 解決策
Add-Content -Path "readonly.txt" -Value "テスト" -Force

パスが存在しない

# ディレクトリも含めて作成
$filePath = "C:\logs\subfolder\app.log"
$directory = Split-Path $filePath -Parent

if (-not (Test-Path $directory)) {
    New-Item -Path $directory -ItemType Directory -Force
}

Add-Content -Path $filePath -Value "ログメッセージ"

改行コードの問題

# Windows形式の改行コード(CRLF)で追記
Add-Content -Path "file.txt" -Value "行1`r`n行2"

# 改行なしで追記
Add-Content -Path "file.txt" -Value "改行なし" -NoNewline

実際の業務での活用例

サーバー監視スクリプト

# サーバーの健全性チェックと結果の記録
$monitoringScript = {
    $logPath = "C:\monitoring\server_status.log"
    $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
    
    # CPU使用率チェック
    $cpuUsage = Get-Counter "\Processor(_Total)\% Processor Time" | 
                Select-Object -ExpandProperty CounterSamples | 
                Select-Object -ExpandProperty CookedValue
    
    # メモリ使用率チェック
    $totalMemory = (Get-CimInstance Win32_ComputerSystem).TotalPhysicalMemory
    $availableMemory = (Get-Counter "\Memory\Available Bytes").CounterSamples.CookedValue
    $memoryUsage = [math]::Round((($totalMemory - $availableMemory) / $totalMemory) * 100, 2)
    
    # ディスク使用率チェック
    $diskUsage = Get-WmiObject -Class Win32_LogicalDisk -Filter "DriveType=3" |
                 Select-Object DeviceID, @{Name="UsedSpace";Expression={[math]::Round((($_.Size - $_.FreeSpace) / $_.Size) * 100, 2)}}
    
    # 結果をログに記録
    Add-Content -Path $logPath -Value "[$timestamp] CPU: $([math]::Round($cpuUsage, 2))%, Memory: $memoryUsage%"
    
    foreach ($disk in $diskUsage) {
        Add-Content -Path $logPath -Value "[$timestamp] Disk $($disk.DeviceID) Usage: $($disk.UsedSpace)%"
    }
}

# スケジュールタスクとして実行

バックアップログの管理

# バックアップ処理とログ記録
function Backup-WithLogging {
    param(
        [string]$SourcePath,
        [string]$DestinationPath,
        [string]$LogPath = "C:\logs\backup.log"
    )
    
    $startTime = Get-Date
    Add-Content -Path $LogPath -Value "[$startTime] バックアップ開始: $SourcePath -> $DestinationPath"
    
    try {
        # バックアップ実行(例:Robocopyを使用)
        $result = robocopy $SourcePath $DestinationPath /E /R:3 /W:5 /LOG+:$LogPath
        
        $endTime = Get-Date
        $duration = $endTime - $startTime
        Add-Content -Path $LogPath -Value "[$endTime] バックアップ完了: 所要時間 $($duration.ToString())"
        
        return $true
    }
    catch {
        $errorTime = Get-Date
        Add-Content -Path $LogPath -Value "[$errorTime] バックアップエラー: $($_.Exception.Message)"
        return $false
    }
}

まとめ

PowerShellのAdd-Contentコマンドレットは、ファイルへの追記操作において非常に強力で柔軟なツールです。

基本機能:

  • 既存ファイルへの安全な追記
  • 複数行や配列の一括追記
  • パイプラインとの連携

実践的な活用:

  • ログファイルの管理と分析
  • レポート生成の自動化
  • 設定ファイルの動的更新
  • データの統合と集約

重要なポイント:

  • エンコーディングの適切な指定
  • エラーハンドリングの実装
  • パフォーマンスの最適化
  • ファイルロックの対処

コメント

タイトルとURLをコピーしました