How to Concatenate Strings in PowerShell

To concatenate strings in PowerShell, put the variables inside double quotes, or join them with the + operator. The -f format operator works too:

$first = 'Alice'
$last  = 'Johnson'

"$first $last"
$first + ' ' + $last
'{0}, {1}' -f $last, $first

Output:

Alice Johnson
Alice Johnson
Johnson, Alice

All three give the same result here. The differences show up with numbers, dates, object properties and loops. I ran every example in PowerShell 7.6 and Windows PowerShell 5.1.

Concatenate a string and a number

With +, the value on the left decides what happens. A number on the left means addition, and a string on the left means joining text:

"1 + '2'   = $(1 + '2')"
"'1' + 2   = $('1' + 2)"
"'Order ' + 1042 = $('Order ' + 1042)"

Output:

1 + '2'   = 3
'1' + 2   = 12
'Order ' + 1042 = Order 1042
PowerShell concatenate string and integer: the left operand decides
The same + gives 3 or 12 depending on the order (PowerShell 7)

If you start with a string, PowerShell converts the number for you. Putting everything in double quotes avoids the question entirely: "Order $id".

Concatenate a string and a date

A string plus a date works, but a date plus a string doesn’t. Format the date yourself so you control how it looks:

$shipDate = [datetime]'2026-09-28 14:30'

'Report_' + $shipDate
'Report_' + $shipDate.ToString('yyyy-MM-dd') + '.csv'
try { $shipDate + '_Report' } catch { "Date first: $($_.Exception.GetType().Name)" }

Output:

Report_09/28/2026 14:30:00
Report_2026-09-28.csv
Date first: MethodException

PowerShell converts the date in the first line with a fixed format (month/day/year and 24-hour time), whatever your regional settings are. For file names, use .ToString('yyyy-MM-dd'), which sorts correctly.

Put object properties inside a string

Inside double quotes, PowerShell only expands the variable name, not the property after the dot. Wrap it in $():

$user = [pscustomobject]@{ Name = 'Alice Johnson'; City = 'Austin' }

"Wrong: $user.Name"
"Right: $($user.Name) from $($user.City)"

Output:

Wrong: @{Name=Alice Johnson; City=Austin}.Name
Right: Alice Johnson from Austin
PowerShell object property inside a double-quoted string needs $()
$user.Name prints the object; $($user.Name) prints the name (PowerShell 7)

The same goes for method calls and math, like "Total: $($price * $qty)". Microsoft explains the rules in about_Quoting_Rules.

Format numbers and currency with -f

For decimals and dollar amounts, the -f operator gives you control over the format:

$price = 1234.5
$qty   = 3

"Plain:     $price"
'Two places: {0:N2}' -f $price
'Currency:  {0:C}' -f ($price * $qty)

Output:

Plain:     1234.5
Two places: 1,234.50
Currency:  $3,703.50

{0:N2} adds thousands separators and two decimal places. {0:C} formats currency using the computer’s regional settings, which is dollars on a US system.

Join a list with a delimiter

-join concatenates every item in an array, with the delimiter between them:

$states = 'Texas', 'California', 'Florida'
"Joined: $($states -join ', ')"

$names = 'Washington', $null, 'Lincoln', '', 'Roosevelt'
"With blanks:  $($names -join ' | ')"
"Blanks removed: $(($names | Where-Object { $_ }) -join ' | ')"

Output:

Joined: Texas, California, Florida
With blanks:  Washington |  | Lincoln |  | Roosevelt
Blanks removed: Washington | Lincoln | Roosevelt

Empty and $null items aren’t skipped. They become empty spots between delimiters, so filter them out first. Microsoft covers the operator in about_Join.

Join-String in PowerShell 7

PowerShell 7 also has Join-String, which can add quotes around each item as it joins:

'Texas', 'California', 'Florida' | Join-String -Separator ', ' -SingleQuote

Output in PowerShell 7:

'Texas', 'California', 'Florida'

Join-String doesn’t exist in Windows PowerShell 5.1. There, use -join. To join with line breaks instead of commas, see how to add a new line in a string.

Concatenate strings inside a loop

Adding to a string with += in a loop is the most common way, and the slowest. I built a 20,000-item string three ways:

$count = 20000

$plus = Measure-Command {
    $text = ''
    foreach ($i in 1..$count) { $text += "Line $i," }
}
$builder = Measure-Command {
    $sb = [System.Text.StringBuilder]::new()
    foreach ($i in 1..$count) { [void]$sb.Append("Line $i,") }
    $text = $sb.ToString()
}
$join = Measure-Command {
    $text = $(foreach ($i in 1..$count) { "Line $i" }) -join ','
}

'+= in a loop:   {0,6:N0} ms' -f $plus.TotalMilliseconds
'StringBuilder:  {0,6:N0} ms' -f $builder.TotalMilliseconds
'-join at end:   {0,6:N0} ms' -f $join.TotalMilliseconds

Output in PowerShell 7 (your times will differ):

+= in a loop:      727 ms
StringBuilder:     130 ms
-join at end:       23 ms

Output in Windows PowerShell 5.1:

+= in a loop:    2,069 ms
StringBuilder:      26 ms
-join at end:       33 ms
PowerShell concatenate strings in a loop: += vs StringBuilder vs -join
+= in a loop took seconds (Windows PowerShell 5.1)

Each += copies the whole string, so the time grows quickly with the number of items. For a few dozen items, it doesn’t matter. For thousands, collect the items and -join them once, or use a StringBuilder.

Frequently Asked Questions

How do I concatenate strings in PowerShell?

Use double quotes, like "$first $last", or the + operator: $first + ' ' + $last. For lists, use $items -join ', '.

How do I concatenate a string and a number in PowerShell?

Put the string first, like 'Order ' + 1042, or use double quotes: "Order $id". A number first means addition.

Why does “$user.Name” print the whole object?

Double quotes only expand the variable, not the property. Use "$($user.Name)" to expand the property.

Does -join skip empty values in PowerShell?

No. $null and empty strings become empty spots between delimiters. Filter them first with Where-Object { $_ }.

What’s the fastest way to concatenate strings in a loop?

Collect the pieces and use -join once, or use a System.Text.StringBuilder. Using += in a large loop is much slower.

If you’re building strings, these guides help too: