Escaping dollar signs in PowerShell path is not working
Instead of messing around with escaping dollar signs, use single quotes '
instead of double quotes "
. It prevents PowerShell expanding $
into a variable. Like so,
$p = "C:\temp\Share\ISO$OEM$"
# Output
C:\temp\Share\ISO$
$p = 'C:\temp\Share\ISO$OEM$'
# Output
C:\temp\Share\ISO$OEM$
If you need to create a path by using variables, consider using Join-Path
. Like so,
$s = "Share"
join-path "C:\temp\$s" '\ISO$OEM$'
# Output
C:\temp\Share\ISO$OEM$
You can actually just use a tick mark to escape the $
like so:
`$
Example:
$number = 5
Write-Host "`$${number}"
# Output: $5
You used double quotes with a single backtick. This is an incorrect combination. In fact, I am not sure that a single backtick alone is sufficient in any case. Your successful options to escape the dollar sign ($) in PowerShell are to use double quotes with a backslash-backtick combination ("\`$find"), or instead to use single quotes with a simple backslash ('\$find'). [However, note the exception at the end about function call parameters.] See below for examples.
Also, for those unfamiliar with the distinction, it is important not to confuse the backtick character (`) with the single-quotation character (') in these escapes.
[SUCCESS] Double quotes as container with backslash-backtick as escape:
PS C:\Temp> 'What is $old?' | ForEach-Object {$_ -replace "\`$old", "(New)"}
What is (New)?
PS C:\Temp>
[FAIL] Double quotes as container with backslash-apostrophe as escape:
PS C:\Temp> 'What is $old?' | ForEach-Object {$_ -replace "\'$old", "(New)"}
What is $old?
PS C:\Temp>
[SUCCESS] Single quotes as container with simple backslash as escape:
PS C:\Temp> 'What is $old?' | ForEach-Object {$_ -replace '\$old', "(New)"}
What is (New)?
PS C:\Temp>
[FAIL] Single quotes as container with backslash-backtick as escape:
PS C:\Temp> 'What is $old?' | ForEach-Object {$_ -replace '\`$old', "(New)"}
What is $old?
PS C:\Temp>
Overall, the easiest option may be to use single quotes as the container and a single backslash as the escape: '\$old'
Update: As if the above were not confusing enough, when you use a function call instead of a command, single quotes are needed without an escape. Trying to use an escape on the function call parameter will not work:
[FAIL] Using an escape in a function parameter:
PS C:\Temp> 'What is $old?' | ForEach-Object {$_.ToString().Replace('\$old', "(New)");}
What is $old?
PS C:\Temp>
[SUCCESS] Using plain single quotes without an escape in a function parameter:
PS C:\Temp> 'What is $old?' | ForEach-Object {$_.ToString().Replace('$old', "(New)");}
What is (New)?
PS C:\Temp>
In my case I needed to escape some $
's used in a string but not others that are variables.
For example, my SSRS instance name has a $
sign:
[ReportServer$SSRS]
To escape the $ sign I use single quotes. Otherwise I use the -join
statement to concatenate variables with the strings containing actual $ signs.
$sql = -join('ALTER DATABASE [ReportServer$', $instanceName,'TempDB]
SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
GO
USE [master]
RESTORE DATABASE [ReportServer$', $instanceName,'TempDB] FROM DISK = N''C:\temp\ReportServerTempDB.BAK'' WITH FILE = 1,
MOVE N''ReportServerTempDB'' TO N''', $sqlDataDrive + "\data_" + $instanceName, '\ReportServer$', $instanceName,'TempDB.mdf'',
MOVE N''ReportServerTempDB_log'' TO N''', $sqlLogDrive + "\log_" + $instanceName, '\ReportServer$', $instanceName,'_TempDBlog.LDF'', NOUNLOAD, REPLACE, RECOVERY, STATS = 5
GO
ALTER DATABASE [ReportServer$', $instanceName,'TempDB]
SET MULTI_USER;
GO
')