322

How do you take a command like the following in PowerShell and split it across multiple lines?

&"C:\Program Files\IIS\Microsoft Web Deploy\msdeploy.exe" -verb:sync -source:contentPath="c:\workspace\xxx\master\Build\_PublishedWebsites\xxx.Web" -dest:contentPath="c:\websites\xxx\wwwroot\,computerName=192.168.1.1,username=administrator,password=xxx"
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
asgerhallas
  • 16,890
  • 6
  • 50
  • 68

8 Answers8

496

Trailing backtick character, i.e.,

&"C:\Program Files\IIS\Microsoft Web Deploy\msdeploy.exe" `
-verb:sync `
-source:contentPath="c:\workspace\xxx\master\Build\_PublishedWebsites\xxx.Web" `
-dest:contentPath="c:\websites\xxx\wwwroot,computerName=192.168.1.1,username=administrator,password=xxx"

White space matters. The required format is Space`Enter.

Myrddin Emrys
  • 42,126
  • 11
  • 38
  • 51
Colin Pickard
  • 45,724
  • 13
  • 98
  • 148
  • 2
    This seems to break command history (up arrow) functionality; as each line shows up as a separate command. Is there a way around this? – Richard Ev Feb 06 '13 at 12:16
  • 2
    If you're running powershell 3 or higher, see github.com/lzybkr/psreadline - history traversal is fixed for multiline statements. – x0n Oct 06 '13 at 23:06
  • 69
    The space in front of the back-tick is required #learned-the-hard-way – Josh Graham Feb 15 '16 at 14:40
  • 49
    @josh-graham And there should NOT be any space (or inline comment) AFTER the back-tick. #learned-the-hard-way – RayLuo Nov 21 '16 at 23:35
  • 1
    Backticks are brittle (as above comments state) and hard to find when parsing or reviewing a file. @StevenPenny 's answer is better if you want easier to debug code. – mjd2 Feb 25 '19 at 22:55
  • You can also split the strings over multiple lines with the subexpression and arithmetic operators $() and +. e.g. -dest:contentPath=$("c:\websites\xxx\wwwroot," + "computerName=192.168.1.1" + ...). A new line can follow each +. – Chris Smith Feb 03 '21 at 07:47
  • For curious like me: Powershell's official doc, page about_Parsing, sec _Line Continuation_ https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_parsing?view=powershell-7.3#line-continuation . – muzimuzhi Z Feb 16 '23 at 12:54
  • backtick is not really a good practice, since any invisible character after it breaks the code – andowero Mar 23 '23 at 14:28
89

Another method for cleaner argument passing would be splatting.

Define your parameters and values as a hashtable like this:

$params = @{ 'class' = 'Win32_BIOS';
             'computername'='SERVER-R2';
             'filter'='drivetype=3';
             'credential'='Administrator' }

And then call your commandlet like this:

Get-WmiObject @params

Microsoft Docs: About Splatting

TechNet Magazine 2011: Windows PowerShell: Splatting

Looks like it works with Powershell 2.0 and up

spottedmahn
  • 14,823
  • 13
  • 108
  • 178
BJHop
  • 1,022
  • 8
  • 7
  • 9
    This is wonderful! AND you can add parameters like this: `$params.add('name','Bob Newhart')` https://ramblingcookiemonster.wordpress.com/2014/12/01/powershell-splatting-build-parameters-dynamically/ – bgmCoder Dec 26 '16 at 21:14
  • 2
    The semicolons are ok but superfluous. Only required if there are multiple values per line. – jim birch Feb 06 '20 at 04:55
  • 2
    This doesn't work for normal shell command, mainly for PowerShell commandlets – Exelian Jul 07 '20 at 09:34
  • This should be the new accepted answer. Splatting is a very standard thing to do nowadays. – Diti Apr 28 '22 at 20:04
47

Ah, and if you have a very long string that you want to break up, say of HTML, you can do it by putting a @ on each side of the outer " - like this:

$mystring = @"
Bob
went
to town
to buy
a fat
pig.
"@

You get exactly this:

Bob
went
to town
to buy
a fat
pig.

And if you are using Notepad++, it will even highlight correctly as a string block.

Now, if you wanted that string to contain double quotes, too, just add them in, like this:

$myvar = "Site"
$mystring = @"
<a href="http://somewhere.com/somelocation">
Bob's $myvar
</a>
"@

You would get exactly this:

<a href="http://somewhere.com/somelocation">
Bob's Site
</a>

However, if you use double-quotes in that @-string like that, Notepad++ doesn't realize that and will switch out the syntax colouring as if it were not quoted or quoted, depending on the case.

And what's better is this: anywhere you insert a $variable, it DOES get interpreted! (If you need the dollar sign in the text, you escape it with a tick mark like this: ``$not-a-variable`.)

NOTICE! If you don't put the final "@ at the very start of the line, it will fail. It took me an hour to figure out that I could not indent that in my code!

Here is MSDN on the subject: Using Windows PowerShell “Here-Strings”

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
bgmCoder
  • 6,205
  • 8
  • 58
  • 105
  • 1
    Neat trick, though if I have a variable $... it seems to not work. I get "the character is not allowed after a here string header..." – tofutim Jan 11 '13 at 21:21
  • I don't think you can break a variable name, just a string. – bgmCoder Jan 11 '13 at 21:44
  • Can you break the string in the source without having the new line characters figure in the result? Like an argument list. – Lorlin Jan 03 '23 at 09:06
25

You can use the backtick operator:

& "C:\Program Files\IIS\Microsoft Web Deploy\msdeploy.exe" `
    -verb:sync `
    -source:contentPath="c:\workspace\xxx\master\Build\_PublishedWebsites\xxx.Web" `
    -dest:contentPath="c:\websites\xxx\wwwroot\,computerName=192.168.1.1,username=administrator,password=xxx"

That's still a little too long for my taste, so I'd use some well-named variables:

$msdeployPath = "C:\Program Files\IIS\Microsoft Web Deploy\msdeploy.exe"
$verbArg = '-verb:sync'
$sourceArg = '-source:contentPath="c:\workspace\xxx\master\Build\_PublishedWebsites\xxx.Web"'
$destArg = '-dest:contentPath="c:\websites\xxx\wwwroot\,computerName=192.168.1.1,username=administrator,password=xxx"'

& $msdeployPath $verbArg $sourceArg $destArg
Aaron Jensen
  • 25,861
  • 15
  • 82
  • 91
  • 2
    I like variable names over other suggestions because it's possibly the most readable option for non powershell experts. If I saw a tutorial/set-up guide that used splatting I would be totally lost at what is going on without a sub-tutorial on splatting. Likewise, backticks seem fragile and probably less well known than simple tried and true PS variables. – Josh Desmond Jul 25 '19 at 18:47
19

If you have a function:

$function:foo | % Invoke @(
  'bar'
  'directory'
  $true
)

If you have a cmdlet:

[PSCustomObject] @{
  Path  = 'bar'
  Type  = 'directory'
  Force = $true
} | New-Item

If you have an application:

{foo.exe @Args} | % Invoke @(
  'bar'
  'directory'
  $true
)

Or

icm {foo.exe @Args} -Args @(
  'bar'
  'directory'
  $true
)
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Zombo
  • 1
  • 62
  • 391
  • 407
6

In PowerShell 5 and PowerShell 5 ISE, it is also possible to use just Shift + Enter for multiline editing (instead of standard backticks ` at the end of each line):

PS> &"C:\Program Files\IIS\Microsoft Web Deploy\msdeploy.exe" # Shift+Enter
>>> -verb:sync # Shift+Enter
>>> -source:contentPath="c:\workspace\xxx\master\Build\_PublishedWebsites\xxx.Web" # Shift+Enter
>>> -dest:contentPath="c:\websites\xxx\wwwroot,computerName=192.168.1.1,username=administrator,password=xxx"
Bad
  • 4,967
  • 4
  • 34
  • 50
5

Another way to break a string across multiple lines is to put an empty expression in the middle of the string, and break it across lines:

sample string:

"stackoverflow stackoverflow stackoverflow stackoverflow stackoverflow"

broken across lines:

"stackoverflow stackoverflow $(
)stackoverflow stack$(
)overflow stackoverflow"
Kirill Yunussov
  • 1,955
  • 1
  • 21
  • 24
4

Splat Method with Calculations

If you choose splat method, beware calculations that are made using other parameters. In practice, sometimes I have to set variables first then create the hash table. Also, the format doesn't require single quotes around the key value or the semi-colon (as mentioned above).

Example of a call to a function that creates an Excel spreadsheet

$title = "Cut-off File Processing on $start_date_long_str"
$title_row = 1
$header_row = 2
$data_row_start = 3
$data_row_end = $($data_row_start + $($file_info_array.Count) - 1)

# use parameter hash table to make code more readable
$params = @{
    title = $title
    title_row = $title_row
    header_row = $header_row
    data_row_start = $data_row_start
    data_row_end = $data_row_end
}
$xl_wksht = Create-Excel-Spreadsheet @params

Note: The file array contains information that will affect how the spreadsheet is populated.

Mark
  • 193
  • 11