Appending data to files allows scripts to add new lines or log entries to existing files on disk without modifying or deleting historical content. PowerShell provides two primary mechanisms for appending: the dedicated content cmdlet Add-Content and the formatting cmdlet switch Out-File -Append (along with its shorthand redirection operator >>).
Appending Plain Text with Add-Content
The Add-Content cmdlet (alias: ac) appends content to a specified item or file. If the file already exists, PowerShell opens the file, moves the write pointer to the end of the file stream, writes the new content followed by a newline, and closes the file handle. If the file does not exist, Add-Content automatically creates it.
Basic Syntax
Add-Content -Path <String> -Value <Object[]> [-Encoding <String>] [-PassThru] [-NoNewline]Add-Content -Path "C:\Logs\activity.log" -Value "Service started at $(Get-Date)"Add-Content -Path "C:\Logs\activity.log" -Value "Connection established at $(Get-Date)"Get-Content "C:\Logs\activity.log"Service started at 09/27/2026 18:55:02
Connection established at 09/27/2026 18:55:08Where:
- Each
Add-Contentcall adds a new line after the file's existing content, rather than replacing it. - If
C:\Logs\activity.logdoesn't exist yet, the first call creates it automatically.
Appending Multiple Lines at Once
Add-Content -Path "C:\Logs\activity.log" -Value @("Backup started", "Backup completed")adn the file activity.log contains:
Service started at 09/27/2026 18:55:02
Connection established at 09/27/2026 18:55:08
Backup started
Backup completedA more complete example with structured log entries:
$LogPath = "$PSScriptRoot\system-events.log"
Add-Content -Path $LogPath -Value "2024-10-24 10:00:00 [INFO] System service initialized."
Add-Content -Path $LogPath -Value "2024-10-24 10:01:15 [WARN] Storage pool capacity exceeded 80%."
Add-Content -Path $LogPath -Value "2024-10-24 10:02:30 [INFO] Garbage collection finished."
Get-Content -Path $LogPathpwsh ./add-content-demo.ps12026-10-24 10:00:00 [INFO] System service initialized.
2026-10-24 10:01:15 [WARN] Storage pool capacity exceeded 80%.
2026-10-24 10:02:30 [INFO] Garbage collection finished.Difference Between Set-Content and Add-Content
Both cmdlets write string data to a file, but they differ fundamentally in how they treat existing content.
Original File: [ Line A, Line B ]
│
┌─────────┴─────────┐
▼ ▼
Set-Content Add-Content
│ │
▼ ▼
Replaces the file Adds text after
with new content the existing text
Result: Result:
[ New Line C ] [ Line A, Line B, New Line C ]Behavioral Comparison
| Feature | Set-Content (alias: sc) |
Add-Content (alias: ac) |
|---|---|---|
| Existing File Action | Overwrites; truncates existing content to 0 bytes before writing. | Preserves; appends new content to the end of the file. |
| Missing File Action | Creates the file. | Creates the file. |
| Missing Directory Action | Throws DirectoryNotFoundException. |
Throws DirectoryNotFoundException. |
| Stream Management | Opens file with write/truncate access. | Opens file with append access (seek-to-end). |
| Performance | Slightly faster (single write). | Slightly slower (must locate end of file). |
| Typical Use Case | Writing configuration files, resetting state, initial exports. | Event logging, accumulating batch job results, audit trails. |
Set-Content -Path "C:\Temp\demo.txt" -Value "First line"
Set-Content -Path "C:\Temp\demo.txt" -Value "Second line"
Write-Output "--- After Set-Content twice ---"
Get-Content "C:\Temp\demo.txt"
Add-Content -Path "C:\Temp\demo2.txt" -Value "First line"
Add-Content -Path "C:\Temp\demo2.txt" -Value "Second line"
Write-Output "--- After Add-Content twice ---"
Get-Content "C:\Temp\demo2.txt"./comparison.ps1--- After Set-Content twice ---
Second line
--- After Add-Content twice ---
First line
Second lineWhere:
- The second
Set-Contentcall overwrites the first line entirely, leaving only"Second line"in the file. - Both
Add-Contentcalls preserved prior content, resulting in both lines appearing in the file.
Practical Examples
Daily Log Rotation Pattern
A common pattern combines both cmdlets: Add-Content for ongoing log entries, and Set-Content (or Move-Item) to start a fresh log periodically.
$logPath = "C:\Logs\daily-activity.log"
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
Add-Content -Path $logPath -Value "[$timestamp] Task executed successfully."./daily-log.ps1
./daily-log.ps1
Get-Content "C:\Logs\daily-activity.log"[2026-09-27 18:59:33] Task executed successfully.
[2026-09-27 18:59:39] Task executed successfully.Transaction Log with Automated Rotation Check
The following script appends operational status records to a persistent transaction log file, evaluates the file size after writing, and rotates the log file if it exceeds a specified size limit.
param (
[string]$LogFile = "$PSScriptRoot\transactions.log",
[double]$MaxSizeBytes = 500KB
)
$ParentDir = Split-Path -Path $LogFile -Parent
if ($ParentDir -and -not (Test-Path -Path $ParentDir -PathType Container)) {
$null = New-Item -ItemType Directory -Path $ParentDir -Force
}
$Timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss.fff"
$Machine = $env:COMPUTERNAME
$Action = "HEALTH_PROBE"
$Status = "SUCCESS"
$LogPayload = "{0} | Node: {1,-15} | Action: {2,-12} | Status: {3}" -f `
$Timestamp, $Machine, $Action, $Status
Add-Content -Path $LogFile -Value $LogPayload -Encoding utf8
$CurrentFile = Get-Item -Path $LogFile
$NeedsRotation = $CurrentFile.Length -ge $MaxSizeBytes
if ($NeedsRotation) {
$ArchiveStamp = Get-Date -Format "yyyyMMdd_HHmmss"
$ArchivedName = "$LogFile.$ArchiveStamp.bak"
Rename-Item -Path $LogFile -NewName $ArchivedName
Write-Warning "Log file exceeded threshold ($($CurrentFile.Length) bytes). Rotated to: $ArchivedName"
}
[PSCustomObject]@{
LogTarget = $LogFile
CurrentBytes = if (Test-Path $LogFile) { (Get-Item $LogFile).Length } else { 0 }
Rotated = $NeedsRotation
LastEntryAdded = $LogPayload
}Where:
Split-PathandNew-Item -ItemType Directoryensure parent directories exist before writing."{0} | Node: {1,-15}..." -f ...uses composite formatting to align log fields into fixed-width columns.Add-Content -Path $LogFile -Value $LogPayloadappends the formatted string safely using UTF-8.Get-Item $LogFile | Lengthchecks whether the file size exceeds the configured threshold.Rename-Itemrotates the log file into a backup archive if the size limit is reached.
Execute the script from the console:
pwsh ./append-transaction-log.ps1LogTarget : C:\Scripts\transactions.log
CurrentBytes : 88
Rotated : False
LastEntryAdded : 2026-10-24 23:55:10.124 | Node: WORKSTATION-01 | Action: HEALTH_PROBE | Status: SUCCESSVerify that consecutive script runs preserve historical entries:
pwsh ./append-transaction-log.ps1
Get-Content -Path "$PSScriptRoot\transactions.log"2026-10-24 23:55:10.124 | Node: WORKSTATION-01 | Action: HEALTH_PROBE | Status: SUCCESS
2026-10-24 23:55:12.458 | Node: WORKSTATION-01 | Action: HEALTH_PROBE | Status: SUCCESS