« Interlude: Crystal Timelapses + Deus Ex: HR | Main | Improve Your Podcast and Screencast Audio with Auphonic »
Sunday
Feb172013

Reliable Path Navigation in PowerShell based on Script Location  

I've forgotten and re-learned this several times in the past month few months –  that's means it's time for a blog post.

Summary: I'm going to show how to make your scripts more resilient to common issues with your current directory.

Let's start with my scenario as shown below. I need my PowerShell script Deploy.PS1 one to copy MyProject.DLL somewhere else.

Snap00251

Our first attempt at this will be to use relative paths like this in Deploy.PS!

copy ..\Bin\Debug\MyProject.DLL D:\outputfolder

The weakness of this approach is that the “current directory” is sensitive to where your PowerShell host is started from. For example if you launch PowerShell.exe by default your location will look something like “C:\users\username”

Also, in the course of your PowerShell session, you may have changed your current directory to some other location.

We need a more reliable way of traversing from where the Deploy.PS1 script exists –  regardless of the current path.

Fortunately this is not very hard!

First, let's figure out the absolute filename for the script. We simply get this from the value of $myinvocation.mycommand.path

    $script_path = $myinvocation.mycommand.path

Now, we find the location of the “Scripts” folder

    $script_folder = Split-Path $script_path -Parent

We go up once more to get to “MyProject”

    $project_path = Split-Path $script_folder -Parent

Navigate down into “bin/Debug”

    $bindebug_path = Join-Path $project_path "bin/Debug"

And finally get the location of the DLL

    $localdll = Join-Path $bindebug_path "MyProject.dll"

Here's the complete script

$script_path = $myinvocation.mycommand.path
$script_folder = Split-Path $script_path -Parent
$project_path = Split-Path $script_folder -Parent
$bindebug_path = Join-Path $project_path "bin/Debug"
$localdll = Join-Path $bindebug_path "MyProject.dll"

So now we've seen three things in action:

  • How to find where the currently runing script is located –  by using the value of $myinvocation.mycommand.path
  • Given a path, how to to get the parent folder –  by using the Split-Path cmdlet
  • How to append paths –  by using the Join-Path cmdlet

If you want to condense this even further, you can get it done in one line:

$localdll = Join-Path $MyInvocation.MyCommand.Path "../../bin/Debug"

 

 

PrintView Printer Friendly Version

EmailEmail Article to Friend

Reader Comments (1)

Perfect, thanks for posting!

March 6, 2013 | Unregistered CommenterLisa

PostPost a New Comment

Enter your information below to add a new comment.
Author Email (optional):
Author URL (optional):
Post:
 
Some HTML allowed: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>