Summary: Learn how to Use Windows PowerShell hash tables with your cmdlets to create powerful commands.
Hey, Scripting Guy! I think I understand hash tables after having read your earlier articles about working with hash tables. What I do not understand is how hash tables work within Windows PowerShell commands. In addition, how do I find Windows PowerShell cmdlets that use hash tables?
—JB
Hello JB,
Microsoft Scripting Guy Ed Wilson here. I spent the Fourth of July playing with Windows PowerShell. The Scripting Wife spent the holiday reading. We both had a great holiday, and we were able to do exactly what we wanted to do for three days—it was wonderful.
Note This is the fourth (and last) blog post in a series of posts discussing the hash table. The first post covered the basics of working with hash tables such as creating a hash table, and adding and removing items from a hash table. The second post went into more detail and discussed programmatically adding items to the hash table, counting items in a hash table, and clearing the contents of the hash table. In the third post, I talked about using a hash table to filter lists by removing duplicate items. In today’s post, I discuss using hash tables with Windows PowerShell cmdlets.
One of the things I did was play around with my Get-Help trick of searching the help contents for specific words (I discussed this trick in the article on Monday in which I detailed the four matching rules that Get-Help utilizes.) To find all of the mentions of hash tables in help, I used several different commands. The commands and their associated output appear here (the command Get-Help Hash-Table is not shown here because I ran it on Monday and the output appears in that article).
PS C:\hsgTest> Get-Help hashtable
Name Category Synopsis
Get-WinEvent Cmdlet Gets events from event logs and event tracing log files on local and rem…
New-WSManSessionOption Cmdlet Creates a WS-Management session option hash table to use as input parame…
ConvertFrom-StringData Cmdlet Converts a string containing one or more key/value pairs to a hash table.
Group-Object Cmdlet Groups objects that contain the same value for specified properties.
about_Arithmetic_Operators HelpFile Describes the operators that perform arithmetic in Windows PowerShell.
about_hash_tables HelpFile Describes how to create, use, and sort hash tables in Windows PowerShell.
PS C:\hsgTest> Get-Help “hash table”
Name Category Synopsis
Get-WinEvent Cmdlet Gets events from event logs and event tracing log files on local and rem…
New-WSManSessionOption Cmdlet Creates a WS-Management session option hash table to use as input parame…
New-ModuleManifest Cmdlet Creates a new module manifest.
Format-Table Cmdlet Formats the output as a table.
ConvertFrom-StringData Cmdlet Converts a string containing one or more key/value pairs to a hash table.
Get-Date Cmdlet Gets the current date and time.
Import-LocalizedData Cmdlet Imports language-specific data into scripts and functions based on the U…
Select-Object Cmdlet Selects specified properties of an object or set of objects. It can also…
Group-Object Cmdlet Groups objects that contain the same value for specified properties.
Sort-Object Cmdlet Sorts objects by property values.
Select-XML Cmdlet Finds text in an XML string or document.
Set-WmiInstance Cmdlet Creates or updates an instance of an existing Windows Management Instrum…
about_Arithmetic_Operators HelpFile Describes the operators that perform arithmetic in Windows PowerShell.
about_Assignment_Operators HelpFile Describes how to use operators to assign values to variables.
about_Automatic_Variables HelpFile Describes variables that store state information for Windows PowerShell.
about_data_sections HelpFile Explains Data sections, which isolate text strings and other read-only
about_hash_tables HelpFile Describes how to create, use, and sort hash tables in Windows PowerShell.
about_preference_variables HelpFile Variables that customize the behavior of Windows PowerShell
about_remote_output HelpFile Describes how to interpret and format the output of remote commands.
about_script_internationalization HelpFile Describes the script internationalization features of Windows PowerShell…
about_Variables HelpFile Describes how variables store values that can be used in Windows
about_Windows_PowerShell_2.0 HelpFile Describes the new features that are included in Windows PowerShell 2.0.
One reason for the three different permutations of hash table is that the term hashtable appears in a few parameter names. The other articles always refer to hash table as two words. The one instance of hash-table in the Get-Winevent article is a bug.
JB, first I would like to play around with the Group-Object cmdlet. It is cool. The Group-Object cmdlet has an ashashtable switched parameter that causes the cmdlet to return a hash table. I like to use this parameter, and store the resulting hash table in a variable. In the following command, I use dir (an alias for the Get-ChildItem cmdlet) to produce a listing of the hsgtest directory. The recurse switch tells the cmdlet to continue retrieving information from nested directories. I pass the returned objects via the pipeline to the select command (select is an alias for the Select-Object cmdlet). I then pipe the custom object (the object only contains two properties: name and fullname) to the Group-Object cmdlet where the results are grouped on the name property and returned as a hash table. The hash table is stored in the $a variable. The command to obtain a directory listing, choose the name and fullname properties, group on the name property, and return a hash table is shown here:
PS C:\hsgTest> $a = dir -Recurse | select name, fullname | Group-Object -Property name –AsHashTable
After I have a hash table stored in the $a variable, I can look at the keys or the values. First I use the keys property to examine the keys stored in the $a variable. The command and associated output appear here:
PS C:\hsgTest> $a.Keys
testfile30.txt
testfile27.txt
testfile21.txt
testfile20.txt
testfile25.txt
testfile10.txt
<output is truncated to save space>
Now, I want to see the values that are stored in the $a variable. This is where things begin to get interesting. The command and associated output appear here in truncated fashion.
PS C:\hsgTest> $a.Values
Name FullName
—- ——–
testfile30.txt C:\hsgTest\testfile30.txt
testfile30.txt C:\hsgTest\hsgtest2\testfile30.txt
testfile30.txt C:\hsgTest\hsgtest2\hsgTest3\testfile30.txt
testfile27.txt C:\hsgTest\hsgtest2\testfile27.txt
testfile21.txt C:\hsgTest\hsgtest2\testfile21.txt
testfile20.txt C:\hsgTest\testfile20.txt
testfile20.txt C:\hsgTest\hsgtest2\testfile20.txt
<output is truncated to save space>
The output above is a bit unexpected because it looks like once again the key and the values are appearing.
In addition, it looks like there are duplicate values for the key. The output of the hash table itself, however, includes grouping information that makes it clear that duplicates are not stored in the $a variable.
PS C:\hsgTest> $a
Name Value
—- —–
testfile30.txt {@{Name=testfile30.txt; FullName=C:\hsgTest\testfile30.txt}, @{Name=testfile30.txt; F…
testfile27.txt {@{Name=testfile27.txt; FullName=C:\hsgTest\hsgtest2\testfile27.txt}}
testfile21.txt {@{Name=testfile21.txt; FullName=C:\hsgTest\hsgtest2\testfile21.txt}}
testfile20.txt {@{Name=testfile20.txt; FullName=C:\hsgTest\testfile20.txt}, @{Name=testfile20.txt; F…
<output truncated to save space>
A closer look reveals that we have a more complex object stored in the values property. To take this closer look I can use the item method to retrieve a specific entry from the hash table. The following command shows the information stored in the value portion of the hash table.I can use the item method to retrieve a specific entry from the hash table. The following command shows the information stored in the value portion of the hash table.
PS C:\hsgTest> $a.Item(“testfile30.txt”)
Name FullName
—- ——–
testfile30.txt C:\hsgTest\testfile30.txt
testfile30.txt C:\hsgTest\hsgtest2\testfile30.txt
testfile30.txt C:\hsgTest\hsgtest2\hsgTest3\testfile30.txt
When I use the item method to retrieve information about the testfile30.txt key, three items are stored in the value. To see only one of those items, I can index into it by using a square bracket and index number (you may recall this is one of my top ten favorite Windows PowerShell tricks). The code to do this is shown here along with the associated output:
PS C:\hsgTest> $a.Item(“testfile30.txt”)[0]
Name FullName
—- ——–
testfile30.txt C:\hsgTest\testfile30.txt
When I address a single item, I can directly access the properties I chose via the Select-Object cmdlet. In the following code, I access the name property, and then I access the fullname property:
PS C:\hsgTest> $a.Item(“testfile30.txt”)[0].name
testfile30.txt
PS C:\hsgTest> $a.Item(“testfile30.txt”)[0].fullname
C:\hsgTest\testfile30.txt
Because I can store lots of different types of things in a hash table (even other hash tables), I do not need to create a custom object via the Select-Object cmdlet. I can, in fact, store an entire fileinfo or directoryinfo object in the hash table. This is illustrated here:
PS C:\hsgTest> $b = dir -Recurse | Group-Object -Property name -AsHashTable
PS C:\hsgTest> $b.Item(“testfile30.txt”)
Directory: C:\hsgTest
Mode LastWriteTime Length Name
-a— 7/1/2011 8:53 PM 0 testfile30.txt
Directory: C:\hsgTest\hsgtest2
Mode LastWriteTime Length Name
-a— 7/1/2011 8:53 PM 0 testfile30.txt
Directory: C:\hsgTest\hsgtest2\hsgTest3
Mode LastWriteTime Length Name
-a— 7/1/2011 8:53 PM 0 testfile30.txt
PS C:\hsgTest> $b.Item(“testfile30.txt”)[0]
Directory: C:\hsgTest
Mode LastWriteTime Length Name
-a— 7/1/2011 8:53 PM 0 testfile30.txt
Any of the properties associated with a fileinfo object are now accessible. In the following code, I retrieve the lastwritetime property from the file:
PS C:\hsgTest> $b.Item(“testfile30.txt”)[0].LastWriteTime
Friday, July 01, 2011 8:53:46 PM
The Get-WinEvent cmdlet can use a hash table for a filter. For an excellent article on that technique, see Use PowerShell Cmdlet to Filter Event Log for Easy Parsing.
The Format-Table cmdlet accepts a hash table to create customized output. The hash table takes the place of a single property, and consists of two key/value pairs. The first key is label and the second key is expression. The expression key accepts a script block. The semicolon separates the two key/value pairs. The ampersand, opening brace, and closing brace (@{}) delineate a hash table. The script block value for the expression key also uses a pair of braces to delineate the script block.
In the following code, dir (an alias for the Get-ChildItem cmdlet) returns a directory listing. The resulting directoryinfo and fileinfo objects are piped to the Where-Object cmdlet (the ? is an alias for the Where-Object cmdlet). The mode property is inspected and only objects that do not have a mode that begins with “d” (a mode of “d—-“ is a directory) are passed to the Format-Table cmdlet (ft is an alias for the Format-Table cmdlet). The name property from the fileinfo object is selected, and a custom label called last written is added to the table. The last written property will display the lastwritetime property from the fileinfo object. The code is shown here:
dir | ? { $_.mode -notmatch ‘^d’ } | ft name, @{Label=”last written” ; Expression = {$_.LastWriteTime}}
The command and associated output are shown in the following figure.
JB, that is all there is to using hash tables inside Windows PowerShell commands. This also ends Hash Table Week. Join me tomorrow when I will talk about playing around with the day of the year. Sound boring? It is not—trust me. See you tomorrow.
I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
Ed Wilson, Microsoft Scripting Guy
0 comments