Use PowerShell to Work Easily with Drives and Paths

Use PowerShell to Work Easily with Drives and Paths

  • Comments 10
  • Likes

Summary: Learn how to use Windows PowerShell drives to simplify access to complex data storage paths.

 

Hey, Scripting Guy! QuestionHey, Scripting Guy! I like using PSDrives. Unfortunately, a problem I have is that I never really know where I am at in the hierarchy. For example, if I am on my fso drive, where does that drive happen to be? Can you provide me with some special Scripting Guy tricks to help me with this problem? I earnestly await your reply.

—CL

 

Hey, Scripting Guy! AnswerHello CL,

Microsoft Scripting Guy Ed Wilson here. I recently made a presentation for a group of Windows PowerShell enthusiasts, and one of the things I showed them was the concept of PSDrives. In fact, I think it is one of the revolutionary concepts that are exposed by Windows PowerShell. The ability to use the same Windows PowerShell cmdlets to work with disparate data sources is simply amazing. That I can use Get-ChildItem and retrieve a list of registry keys, certificates, files, folders, variables, aliases, and environmental variables makes Windows PowerShell truly a power(ful) shell.

I love creating custom PSDrives to simplify access to my Hey, Scripting Guy! Blog posts and scripts. To do this, I use the New-PSDrive cmdlet, specify the name of the provider (filesystem), and provide it with the name of the drive and the path to the root of the new drive. Here is the command I use on my laptop to create my special HSG drive:

New-PSDrive -PSProvider filesystem -Root C:\data\ScriptingGuys\2011 -Name hsg

When the command runs, it returns information about the newly created drive. The information is contained in the PSDriveInfo object that is shown here:

14:39:01 C:\> New-PSDrive -PSProvider filesystem -Root C:\data\ScriptingGuys\2011 -Name hsg | gm

 

   TypeName: System.Management.Automation.PSDriveInfo

 

Name                           MemberType                 Definition

CompareTo                   Method                         int CompareTo(System.Management.Automation.PSDriveInfo drive), in...

Equals                           Method                         bool Equals(System.Object obj), bool Equals(System.Management.Aut...

GetHashCode                Method                         int GetHashCode()

GetType                        Method                         type GetType()

ToString                        Method                         string ToString()

Credential                     Property                        System.Management.Automation.PSCredential Credential {get;}

CurrentLocation             Property                        System.String CurrentLocation {get;set;}

Description                    Property                        System.String Description {get;set;}

Name                           Property                        System.String Name {get;}

Provider                        Property                        System.Management.Automation.ProviderInfo Provider {get;}

Root                             Property                        System.String Root {get;}

Free                              ScriptProperty               System.Object Free {get=## Ensure that this is a FileSystem drive...

Used                             ScriptProperty               System.Object Used {get=## Ensure that this is a FileSystem drive...  

 

After I have created my new PSDrive, I can change my working directory location to that drive. By changing my working directory, I gain easy access to the files and folders in that location. To change location to a new drive, I can use the Set-Location cmdlet and provide it with the name of the new PSDrive. In addition, to using the cmdlet name directly, there are three aliases that can also be used from the command line: cd, chdir, and sl. The following command uses the alias cd to change the working location to the hsg PSDrive. The Windows PowerShell prompt changes to reflect the new location (I have a custom Windows PowerShell prompt that displays the current time as well as the current location):

14:56:50 C:\> cd hsg:

14:57:44 hsg:\>

If I want to return to the C: drive, I can once again use the cd alias:

14:57:44 hsg:\> cd c:

15:00:31 C:\>

I use the up arrow to retrieve my previous command and return to the HSG drive. When I am on my HSG drive, I can use the Get-Location cmdlet to retrieve my current location. The default view returns only the path, as shown here:

15:03:30 hsg:\> Get-Location 

Path

----

hsg:\

Okay, I will admit the default is basically useless when working interactively from the Windows PowerShell console because the default Windows PowerShell prompt includes the current location. However, as with everything else in Windows PowerShell, the Get-Location cmdlet returns an object. This means there are additional properties and methods that are available. A quick use of the Get-Member cmdlet shows me there are some interesting properties that could be helpful. The command to retrieve the members from the PathInfo object is shown here along with the associated output:

15:04:14 hsg:\> 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                        System.String Path {get;}

Provider                        Property                        System.Management.Automation.ProviderInfo Provider {get;}

ProviderPath                  Property                        System.String ProviderPath {get;}

 

The property that looks interesting to me is the ProviderPath property. To see if this will help me to resolve the actual path to the PSDrive, I pipe the output to the Format-List cmdlet. The command and associated output are shown here:

15:04:20 hsg:\> Get-Location | fl *

 

Drive:                hsg

Provider:           Microsoft.PowerShell.Core\FileSystem

ProviderPath:     C:\data\ScriptingGuys\2011\

Path:                 hsg:\

 

Because the ProviderPath is a property of the PathInfo object, it means I can access it directly by using a dotted notation. The command to display only the value contained in the ProviderPath property is shown here along with the associated output:

15:04:32 hsg:\> (Get-Location).providerpath

C:\data\ScriptingGuys\2011\

The Convert-Path cmdlet knows how to convert a PSDrive for a file system location to the actual path to that filesystem location. In the following command, I use the Convert-Path cmdlet to convert the path to the HSG: drive:

15:17:20 hsg:\> Convert-Path -Path HSG:

C:\data\ScriptingGuys\2011\

It might be possible that I do not know where my actual working directory resides—or even what it is. This may be the situation when running inside a script. I can therefore use the Get-Location cmdlet to find out where my current working directory resides, and pass it to the Convert-Path cmdlet. The command and the associated output are shown here:

15:20:19 hsg:\> Convert-Path -Path (Get-Location)

C:\data\ScriptingGuys\2011\

If I am looking for PSDrives, I can use the Get-PSDrive cmdlet. If I do not supply any parameters, it will return all of the PSDrives on the system. However, because I am only concerned with PSDrives that are associated with the filesystem, I can specify that I only want PSDrives from the filesystem PSProvider. The command to return only PSDrives that are associated with the filesystem PSProvider is shown here:

Get-PSDrive -PSProvider filesystem

The command and associated output are shown in the following figure.

Image of command and associated output

When switching working locations, I like to use the Push-Location cmdlet (alias is pushd) and Pop-Location (alias is popd) to store my current location, switch to another location, and then return to the previous location. As a simple example, I am going to store my current location (current c:\), change the working location to the HSG: drive, get a directory output, and then return to my original location (c:\). Here are the commands that accomplish these tasks:

Push-Location

Set-Location hsg:

Get-ChildItem

Pop-Location

In the following figure, I use aliases to accomplish these tasks. The figure includes the commands and the associated output.

Image of commands and associated output

As long as I am talking about Windows PowerShell cmdlets that help in working with paths and locations, I may as well talk about the Resolve-Path cmdlet. It is cool and very powerful when working at the Windows PowerShell console. It allows me to use wildcard characters in path names, and it will resolve the path and output all the paths that match the wildcard character pattern. An example of this technique is shown here:

15:58:30 C:\> Resolve-Path c:\da*\*\*11

 

Path

C:\data\BookScripts_VbScript\ch11

C:\data\Presentation\RoadToTechEd_2011

C:\data\Presentation\TechReady_2011

C:\data\ScriptingGuys\2011

The output from the Resolve-Path cmdlet returns the same PathInfo objects that were returned earlier. This means that I can use the Where-Object cmdlet to find only paths that are related to scripting. This command is shown here (? Is an alias for the Where-Object cmdlet):

Resolve-Path c:\da*\*\*11 | ? { $_.path -match 'scripting'}

I could even send the output to a ForEach-Object cmdlet and use the Get-ChildItem cmdlet to query each of the returned paths. The command to perform this action is shown here (the % symbol is an alias for ForEach-Object and gci is an alias for Get-ChildItem):

Resolve-Path c:\da*\*\*11 | ? { $_.path -match 'scripting'} | % {gci $_.path}

 

CL, that is all there is to working with paths and PSDrives in Windows PowerShell. Thank you for your question, and I invite you to join me for more cool stuff with Windows PowerShell.

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

 

 

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • Hi Ed,

    thanks for reminding me of the CmdLets, I hardly used like "Resolve-Path" and "Convert-Path" ... maybe because I rarely create my own Psdrives!

    there is one more thing we can do to help CL with his problem: "that I never really know where I am at in the hierarchy"

    We can combine your hint regarding the providerpath of (get-Location) to the standard prompt function:

      $(if (test-path variable:/PSDebugContext) { '[DBG]: ' } `

      else { '' }) + 'PS ' + $(Get-Location) + `

      $(if ($nestedpromptlevel -ge 1) { '>>' }) + '> ' `

    which gives us:

    function prompt { `

      $(if (test-path variable:/PSDebugContext) { '[DBG]: ' } `

      else { '' }) + 'PS ' + $(Get-Location).providerpath + `

      $(if ($nestedpromptlevel -ge 1) { '>>' }) + '> ' `

    }

    Noticed the change?

    "$(Get-Location)" became "$(Get-Location).providerpath"

    which will show up the following prompt as result of "cd hsg:"

    "PS C:\data\ScriptingGuys\2011\> "

    or if we issue a "cd hklm:\system" we get:

    "PS HKEY_LOCAL_MACHINE\system> "

    I personally would omit the leading "PS " but you can do whatever you like with your own prompt function, even colorize the output !

    Hope that helps CL :-)

    Klaus

  • @Klaus I am constantly using the Get-Command cmdlet to examine cmdlets that are available, and to remind myself to use cmdlets I have not used in a while ... this really becomes an issue when one has lots of modules each of which can provide many additional cmdlets. That is a cool idea about modifying the prompt function ... a nice change. I recently modified my prompt function to include the time stamp ... this makes it much better when using a transcript of commands as it lets you know WHEN the command was run, and therefore provides the chance to match things up in event logs.

  • Thanks for the post. Can we use this for a different drive? Ie, can we create a psdrive "d:\app" folder?

  • Why are you using this:
    Push-Location
    Set-Location hsg:
    and not this?
    Push-Location hsg: