April 21st, 2015

Location, Location, Location in PowerShell

Doctor Scripto
Scripter

Summary: Microsoft Scripting Guy, Ed Wilson, talks about managing locations in Windows PowerShell.

Hey, Scripting Guy! Question 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

Hey, Scripting Guy! Answer 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:

Image of rain

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:

Image 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 

Author

The "Scripting Guys" is a historical title passed from scripter to scripter. The current revision has morphed into our good friend Doctor Scripto who has been with us since the very beginning.

0 comments

Discussion are closed.