Posey's Tips & Tricks

How To Use PowerShell Splatting

Despite its weird name, splatting can be a really handy technique if you create a lot of PowerShell scripts.

If you have worked with PowerShell for any length of time, you have no doubt seen instances in which a command (or rather, a command's output) has been mapped to a variable. For example, I could create a variable called $VMs that contains a list of all of my Hyper-V virtual machines (VMs) by using the following command:

$VMs = Get-VM

If you look at Figure 1, you can see that by calling the $VMs variable, I see the same output that I would have seen if I had entered the Get-VM cmdlet directly.

[Click on image for larger view.] Figure 1: This is the normal way of mapping a command to a variable.

Splatting is kind of a variation on this technique. Rather than mapping an entire cmdlet to a variable, splatting lets you store the command's input in a variable (or, more precisely, a hash table). This technique can save you a lot of typing when creating complex scripts.

Let me show you a really simple example of how splatting works, and then I will move on to a more practical example.

Earlier, I showed you how to use the Get-VM cmdlet to retrieve a list of Hyper-V VMs. When you use the Get-VM cmdlet without any parameters, you will end up with a list of every VM on the server. However, the command also allows you to specify the name of one individual VM.

[Click on image for larger view.] Figure 2: The Get-VM cmdlet accepts a number of different input parameters.

If you look at Figure 2, you can see the full command syntax for the Get-VM cmdlet. As you can see in the figure, the cmdlet accepts a number of different input parameters, one of which is -Name. You can use Name to specify the name of a VM. Therefore, if I was interested in manually retrieving information about a VM named VM1, I could enter a command like this:

Get-VM -Name VM1

With that in mind, consider what I said earlier about storing parameters in hash tables. Hash tables are a special type of array that lets you store a series of key/value pairs. Most of the time, hash tables are used to store two related pieces of information. Suppose, for example, that I wanted to create a hash table that lists types of fruit and their colors. The code for creating such a hash table would look like this:

$Fruit=@{ "Apple"  = "Red";
  "Grape" = "Purple"
"Lime" = "Green" }

As you can see, the hash table is made up of keys and values. In this case, the keys are types of fruit and the values are their colors.

This same basic concept translates into storing PowerShell input parameters and their values. With that said, let's go back to my earlier example of retrieving information about a VM named VM1. Rather than append -Name VM1 directly to the command, I could write the key (-Name) and its value (VM1) to a hash table. Here is what such a command would look like:

$Name = @{Name =  "VM1"}

I can then append the $Name variable that I just created directly to the Get-VM cmdlet. The trick to making this work is that I would need to replace the "$" in the variable's name with an "@" sign. Here is what the command would look like:

Get-VM @Name

If you look at Figure 3, you can see the normal way of getting information about a specific VM, and then you can see how I used splatting to do the same thing.

Figure 3: I used a hash table to feed parameters to a PowerShell cmdlet.

As I said earlier, this is a simple example. Splatting is most useful when you need to repeatedly use a PowerShell cmdlet that requires lots of parameters. One cmdlet that supports numerous parameters is Get-ChildItem. Let's pretend that we, for whatever reason, need to run Get-ChildItem against C:\, and that we want to show hidden items but do not want to perform a recursive listing. If you look at the command syntax shown in Figure 4, you can see that the parameters that we need to reference include -Path, -Hidden and -Recurse.

[Click on image for larger view.] Figure 4: This is the syntax for the Get-ChildItem cmdlet.

To set up a hash table containing all of these parameters, I would enter the following command:

$Data = @{Path="C:\";  Hidden=$True; Recurse=$False}

If I then type Get-ChildItem @Data, it will do the same thing as if I had typed the command long-form, specifying all of the parameters that I want to use. You can see what this looks like in Figure 5.

Figure 5: I have combined multiple parameters into a single hash table.

About the Author

Brien Posey is a 22-time Microsoft MVP with decades of IT experience. As a freelance writer, Posey has written thousands of articles and contributed to several dozen books on a wide variety of IT topics. Prior to going freelance, Posey was a CIO for a national chain of hospitals and health care facilities. He has also served as a network administrator for some of the country's largest insurance companies and for the Department of Defense at Fort Knox. In addition to his continued work in IT, Posey has spent the last several years actively training as a commercial scientist-astronaut candidate in preparation to fly on a mission to study polar mesospheric clouds from space. You can follow his spaceflight training on his Web site.


comments powered by Disqus

Subscribe on YouTube