Summary: Microsoft Scripting Guy, Ed Wilson, talks about managing locations in Windows PowerShell.
Hey, Scripting Guy! I don’t understand what is the big deal with Get-Location. I mean, I can look and see where I am at, so why do I need Get-Location? For that matter, what are a PushD and a PopD? It says it has something to do with a stack, but I don’t know where that stack is, or even what a stack is. Can you help?
—DW
Hello DW,
Microsoft Scripting Guy, Ed Wilson, is here. The weather in Charlotte finally cleared up. It has been rather cold and wet the past couple days. This is kind of bad because the Windows PowerShell Summit is taking place this week in Charlotte, and we have had nice weather for the past week or so—so I was hoping my friends from other places would see the city in a better light. In fact, Windows PowerShell MVP, Sean Kearney, posted this picture on his Facebook page:
Oh, well. Like I said, it is clearing up, and it should be lovely for the next few days.
The thing that is important about location in Windows PowerShell is that the location can be anywhere. Remember yesterday's post, Find and Use Windows PowerShell Providers? Each of those providers exposes Windows PowerShell drives. So the location may be drive C of your file system—but it could just as easily be the Alias: drive that exposes Windows PowerShell aliases and their associated values.
As you might expect, the Get-Location cmdlet returns an object. This might not be a surprise because everything in Windows PowerShell is an object. And just like most other objects, it returns default information. But there is also additional information available. As shown here, when I type Get-Location, by default, it returns the path:
PS C:\fso2> Get-Location
Path
----
C:\fso2
This information may seem a bit redundant. I mean, I can look at my Windows PowerShell prompt, and if it is in the default configuration, it already shows me my location. But by piping the object that is returned by the Get-Location cmdlet to the Get-Member cmdlet, I can see that I actually have a PathInfo object, and that there is more than only path information available. This is shown here:
PS C:\fso2> Get-Location | gm
TypeName: System.Management.Automation.PathInfo
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
Drive Property System.Management.Automation.PSDriveInfo Drive {get;}
Path Property string Path {get;}
Provider Property System.Management.Automation.ProviderInfo Provider {get;}
ProviderPath Property string ProviderPath {get;}
The easiest way to see the additional properties is to pipe the object returned by Get-Location to the Format-List cmdlet and select all of the properties by using the asterisk wildcard character. This command and its associated output are shown here:
PS C:\fso2> Get-Location | Format-List *
Drive : C
Provider : Microsoft.PowerShell.Core\FileSystem
ProviderPath : C:\fso2
Path : C:\fso2
To change my current location, I use the Set-Location cmdlet. This is a basic command. In fact, there are three aliases created by default for this command:
PS C:\> Get-Alias -Definition set-location
CommandType Name ModuleName
----------- ---- ----------
Alias cd -> Set-Location
Alias chdir -> Set-Location
Alias sl -> Set-Location
If I want to change my location to a particular folder, I can use any of the above aliases or type the complete cmdlet name. To go to a particular folder, I can use the command that is shown here:
PS C:\> sl c:\fso1
But if I want to return to the root of drive C, I must follow it with a backslash. For example, if I just use sl c:, it does produce an error, but it does not move to the root drive. This is shown here:
PS C:\fso1> sl c:
PS C:\fso1> sl c:\
PS C:\>
What is a stack?
You can think of a stack as simply a pile—like the following pile of books:
If I want to retrieve a book from the pile, in general, I will remove the book from the top of the pile (or stack). This book is the last one that I added to the stack. In computer terms, this is referred to as "last in, first out" (LIFO). In book pile terms, it is referred to as not making a mess.
So, a stack is simply a collection of elements (or items) that can be of any type. For example, I could have a stack of DVDs or stack of CDs in addition to my stack of books. My book stack has two methods: add and remove. In computer terms, a stack has two methods: push and pop. An item is pushed to the stack or popped off the stack. In Windows PowerShell, there are two associated cmdlets, Push-Location and Pop-Location. They also have aliases as shown here:
PS C:\> Get-Alias pushd, popd
CommandType Name ModuleName
----------- ---- ----------
Alias pushd -> Push-Location
Alias popd -> Pop-Location
Location information is therefore stored in a stack. By default, this location stack is not named. So why do I care about this stuff? Well, certainly, I can CD around or SL around. But this can begin to be a lot of typing. Here is an example:
PS C:\> sl C:\fso
PS C:\fso> sl c:\
PS C:\> sl E:\Data\ScriptingGuys\2015\HSG_4_20_15
PS E:\Data\ScriptingGuys\2015\HSG_4_20_15> sl 'C:\Users\ed\SkyDrive\Pictures\Camera Roll'
PS C:\Users\ed\SkyDrive\Pictures\Camera Roll> sl E:\Data\BookDOcs\PS5_sbs_book\Scripts\Scripts_ch12
PS E:\Data\BookDOcs\PS5_sbs_book\Scripts\Scripts_ch12>
Unfortunately, even when I remember to use Tab completion and IntelliSense in the Windows PowerShell ISE, this rapidly becomes unwieldy. One of the issues with multiterabyte drives is that the file system structure seems to become complex, and the paths go on and on and on. This makes working from the command line (even from Windows PowerShell) a major pain.
It also can become a source of errors—especially when using Tab completion. When the folder names begin to look the same (such as my weekly folders for the Hey, Scripting Guy! Blog), you really need to pay attention to what you are doing. And anytime you have to rely on paying attention, you are asking for trouble. (As an aside, on MCSE exams, anytime the answer contains “… and instruct the user how to properly…”—that is not the right answer!)
So, what is the right answer? Well, in this case, it involves using Push-Location and Pop-Location (or PushD and PopD as the alias names).
PS C:\> pushd C:\fso
PS C:\fso> pushd c:\
PS C:\> pushd E:\Data\ScriptingGuys\2015\HSG_4_20_15
PS E:\Data\ScriptingGuys\2015\HSG_4_20_15> pushd 'C:\Users\ed\SkyDrive\Pictures\Camera Roll'
PS C:\Users\ed\SkyDrive\Pictures\Camera Roll> pushd E:\Data\BookDOcs\PS5_sbs_book\Scripts\Scripts_ch12
PS E:\Data\BookDOcs\PS5_sbs_book\Scripts\Scripts_ch12>
If I want to see where I have been, I can use the Get-Location cmdlet, but I also specify –Stack. This causes the cmdlet to return the locations stored on the current stack (the default stack). Because I have not named a stack, I am using my default unnamed stack. This makes it easy, because I now use –Stack and it returns what I want. This is shown here:
PS E:\Data\BookDOcs\PS5_sbs_book\Scripts\Scripts_ch12> Get-Location -Stack
Path
----
C:\Users\ed\SkyDrive\Pictures\Camera Roll
E:\Data\ScriptingGuys\2015\HSG_4_20_15
C:\
C:\fso
C:\
Remember that a stack is LIFO. This means that if I begin to pop items off the stack (by using the alias PopD for Pop-Location), I should return to the last place I was. This is shown here:
PS E:\Data\BookDOcs\PS5_sbs_book\Scripts\Scripts_ch12> popd
PS C:\Users\ed\SkyDrive\Pictures\Camera Roll>
What does the stack look like? I use the Up arrow and retrieve the Get-Location –Stack command. As shown here, the content of the default location stack now appears:
PS C:\Users\ed\SkyDrive\Pictures\Camera Roll> Get-Location -Stack
Path
----
E:\Data\ScriptingGuys\2015\HSG_4_20_15
C:\
C:\fso
C:\
Now if I use PopD, I will go to the Scripting Guy folder. To get a feel for the way it works, I once again check the stack all the way until the stack is empty. This is shown here:
PS C:\Users\ed\SkyDrive\Pictures\Camera Roll> popd
PS E:\Data\ScriptingGuys\2015\HSG_4_20_15> Get-Location -Stack
Path
----
C:\
C:\fso
C:\
PS E:\Data\ScriptingGuys\2015\HSG_4_20_15> popd
PS C:\> Get-Location -Stack
Path
----
C:\fso
C:\
PS C:\> popd
PS C:\fso> Get-Location -Stack
Path
----
C:\
PS C:\fso> popd
PS C:\>
Now that I am back to the root drive, I check the stack. It is empty.
PS C:\> Get-Location -Stack
PS C:\>
DW, that is all there is to using location in Windows PowerShell. Provider Week will continue tomorrow when I will talk about more cool stuff.
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