There can be a lot of confusion over when to use single and double quotes in PowerShell. Not to worry, this confusion carries over in a lot of programming and scripting languages, such as Perl. I figured, after seeing this tweet, to give a quick run down of when to use which one.
This tweet is an example of what to do, and what not to do, but is missing an explanation as to why. So I figured I’d try and explain it, and why there are differences.
Both style quotes delimit a string, however the behavior of them are different1. Generally speaking you want to use single quotes for all strings as this makes the PowerShell processor treat it as a string and that is it. If you use a double quote however, PowerShell reads every character in the string, and looks for characters that can be substituted for a variable defined outside the string, or are actually evaluated as powershell operations. Lets take a look at an example
1 2 3 4
In these 2 lines, the execution is essentially the same, nothing special happens. Now lets see what PowerShell does when we throw in a variable:
1 2 3 4 5
I also mentioned that with double quotes, using
$ will cause PowerShell to evaluate functions as well. A simple example would be something like this:
1 2 3 4
Now, if we go back and look at Trevor’s tweet, what we can see is the top “don’t” example has two paths to copy files. Notice something special about the paths, they have spaces in. If you ever work with file paths that have spaces in, you have to quote the entire path. Quoting the string is not the same as quoting the path, and what we can see in this example is that double quotes are used in passing the two paths to the
Start-Process command. What doesn’t happen is the double quotes from the variable definition on line 2 and 3 are not carried over into the string as well. So what should be 2 arguments actually becomes 4. Lets see that at work:
1 2 3 4
In arguments, every space is a delimiter for the next argument, so “C:\Departments\Marketing” is one, then “Group\” is another, and so on. So what’s going on in the second example? Well, both single and double quotes are being used, and string.format replacements are being introduced2. This allows us to still put variables into single quoted strings, and have double quotes to escape the path.
1 2 3 4 5
So now our argument list has quoted paths as required.
There are other ways to use quotes3 that allows you to put double quotes inside a double quoted string. You basically do the quotes twice. So to put a single double quote in string you do them twice. An example would be:
I have an issue doing this because it very quickly and easily becomes confusing trying to keep a track of the number of quotes you have used, and reading the code becomes that much harder.
I made a footnote comment about performance difference as well. In terms of single strings, you don’t really notice a performance difference, but when it comes to itterating over several strings, it starts to build up. Here is a simple test.
1 2 3 4 5 6 7 8 9 10 11 12 13 14
Basically just writing out the word test using single and double quotes. Here’s the output:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
In this simple example over 100 string itterations, and no variable inclusions, you can see that double quotes is just over double the execution time of single quotes. To give some perspective, the average time for a blink is 300-400 milliseconds, so the difference is neglegable, but I’m also running on a fairly powerful machine, and the performance scales with the system being executed on. Give it a shot.
So my general rule of thumb? I try to use single quotes everywhere, and if I have to put variables in the string I tend to use the
-f operator. As a side note, I just skimmed a bunch of my older posts and can see where I’ve gone from using double quotes to single quotes as I’ve been going. At some points using
-f operator with double quoted strings as well. We all learn new stuffs.
If you want to learn more about quoting strings, you can see