Reliable Path Navigation in PowerShell based on Script Location
Sunday, February 17, 2013 at 11:42AM 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.
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"
Reader Comments (1)
Perfect, thanks for posting!