Bulk Remove Variables, Carefully

Ever have one of those situations where you need to remove, or perhaps reinitialize, a set of variables and have to deal with remembering them all? This doesn’t happen often, but there are times when I need to clear, or remove, variables between loop iterations. You either need to keep track of all your variable names, or — and I wouldn’t recommend this so much — do a Remove-Variable -Name *. While the help on PowerShell 5.1.14394.1000 (5.1 preview version), says that Remove-Variable doesn’t accept wildcards, it does, and I think it always has.

Let’s start with the below example. These few lines do the following: 1. Return the number of variables in the PowerShell session, 2. Add a new variable x, 3. Return the number of variables again, 4. Remove all the variables I can (some can’t be removed), 5. Return the number of variables again (again), and 6. See if I can return my variable x.

[tommymaynard@srv01 c/~]$ (Get-Variable).Count
51
[tommymaynard@srv01 c/~]$ New-Variable -Name x -Value 'string'
[tommymaynard@srv01 c/~]$ (Get-Variable).Count
52
[tommymaynard@srv01 c/~]$ Remove-Variable -Name * -ErrorAction SilentlyContinue
[tommymaynard@srv01 c/~]$ (Get-Variable).Count
29
[tommymaynard@srv01 c/~]$ Get-Variable -Name x
Get-Variable : Cannot find a variable with the name 'x'...

While we can do this to remove the variables we’ve created in the session, we end up removing variables that weren’t necessary to remove. We’re better than this.

In the next example, we’ll add a variable prefix “dog” to all of our variables. This will allow us to find all of the variables by prefix, and then delete just those. Not a bad idea really, but it wasn’t my first thought.

[tommymaynard@srv01 c/~]$ New-Variable -Name dog1 -Value 'string1'
[tommymaynard@srv01 c/~]$ New-Variable -Name dog2 -Value 'string2'
[tommymaynard@srv01 c/~]$ New-Variable -Name dog3 -Value 'string3'
[tommymaynard@srv01 c/~]$ Get-Variable -Name dog*

Name                           Value
----                           -----
dog1                           string1
dog2                           string2
dog3                           string3

[tommymaynard@srv01 c/~]$ Remove-Variable -Name dog*
[tommymaynard@srv01 c/~]$ Get-Variable -Name dog*
[tommymaynard@srv01 c/~]$ # No results, as they've been deleted.

Had I thought of the above option first, I might’ve just gone with that idea, but let me share what I was really thinking. It’s involves the description property. When we create our variables with New-Variable, we have the option to set more than just the Name and Value. Let’s take a look at the below example, and then discuss it.

[tommymaynard@srv01 c/~]$ New-Variable -Name a -Value 'stringA' -Description (Get-Date)
[tommymaynard@srv01 c/~]$ $StartDate = Get-Date
[tommymaynard@srv01 c/~]$ New-Variable -Name b -Value 'stringB' -Description (Get-Date)
[tommymaynard@srv01 c/~]$ New-Variable -Name c -Value 'stringC' -Description (Get-Date)
[tommymaynard@srv01 c/~]$ Get-Variable -Name a,b,c

Name                           Value
----                           -----
a                              stringA
b                              stringB
c                              stringC

[tommymaynard@srv01 c/~]$ Get-Variable -Name a,b,c | Select-Object Name,Value,Description

Name Value   Description
---- -----   -----------
a    stringA 11/03/2016 20:52:41
b    stringB 11/03/2016 20:53:05
c    stringc 11/03/2016 20:53:20

Now, it’s important to remember that a variable’s description property is a string. This means that when we put the current date in the property, it was converted to a string. That means that Thursday, November 3, 2016 20:53:20 PM became this: 11/03/2016 20:53:20. What we’ll need to do is convert it back to a datetime before we compare. We do that in the below example by casting the description property as a datetime object. If it’s not clear yet, our end goal is to remove variables that were created after a specific point in time.

[tommymaynard@srv01 c/~]$ Get-Variable -Name a,b,c | Where-Object {[datetime]$_.Description -gt $StartDate}

Name                           Value
----                           -----
b                              stringB
c                              stringC

We can also use the Get-Date cmdlet to do this, as well.

[tommymaynard@srv01 c/~]$ Get-Variable -Name a,b,c | Where-Object {(Get-Date -Format $_.Description) -gt $StartDate}

Name                           Value
----                           -----
b                              stringB
c                              stringC

Since we can now isolate the variables we created after a specific time, we can go ahead and blow them away. Here goes:

[tommymaynard@srv01 c/~]$ Get-Variable -Name a,b,c | Where-Object {(Get-Date -Format $_.Description) -gt $StartDate} | Remove-Variable
[tommymaynard@srv01 c/~]$ Get-Variable a,b,c

Name                           Value
----                           -----
a                              stringA
Get-Variable : Cannot find a variable with the name 'b'.
At line:1 char:1
+ Get-Variable a,b,c
+ ~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (b:String) [Get-Variable], ItemNotFoundException
    + FullyQualifiedErrorId : VariableNotFound,Microsoft.PowerShell.Commands.GetVariableCommand

Get-Variable : Cannot find a variable with the name 'c'.
At line:1 char:1
+ Get-Variable a,b,c
+ ~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (c:String) [Get-Variable], ItemNotFoundException
    + FullyQualifiedErrorId : VariableNotFound,Microsoft.PowerShell.Commands.GetVariableCommand

Well, that’s it for today. Now you can use description property of your variables to hold the time in which they were created. This will allow you to selective remove any of them based on a start time. I like it, although the whole prefix thing might be an easier option.

Leave a Reply

Your email address will not be published.