• Skip to primary navigation
  • Skip to main content
  • Skip to primary sidebar
Think PowerShell

Think PowerShell

PowerShell for IT Pros

  • About
    • Who I Am
    • Why I Blog
    • Privacy Policy
  • Resources
    • More PowerShell Sites
    • Post Series Index
  • Get Help
  • Show Search
Hide Search

Add Script Flexibility with Relative File Paths

Aaron Rothstein · February 15, 2016 · 11 Comments

Folder Contents Screenshot

Using relative file paths for your PowerShell script’s supporting files ensure it continues to work when the script and files get moved around. Here’s how.

Unpredictable File Paths

My first intensive use of PowerShell was for scripting software installations/configurations in SCCM packages. It seemed like every situation called for something above and beyond a straightforward MSI install.

I would develop and test the SCCM package on my local system with a sandbox VM prior to deploying in SCCM. The SCCM client would then download that package to a cached location on each individual client. From development to deployment, I couldn’t guarantee the absolute file path of my script and any supporting files would be constant. I needed my script to be able to figure out where the supporting files were in relation to itself.

The newer way: $PSScriptRoot

$PSScriptRoot is an Automatic Variable, which are built-in variables that contain information about the PowerShell environment itself. $PSScriptRoot contains the directory path of the script being executed currently. Originally $PSScriptRoot was only applicable to script modules (.psm1), but beginning with PowerShell 3.0, it works for all PowerShell script files.

From the console if I type $PSScriptRoot and press ENTER, it returns nothing. $PSScriptRoot only gets a value when a script is executing, and then is destroyed when the script terminates.

PS C:\Users\aaron> $PSScriptRoot


PS C:\Users\aaron>

Let’s say I have a script and config file sitting in C:\TEMP\DemoScript. I would concatenate the value of $PSScriptRoot with  a backslash and the config file name:

# DemoScript.ps1

$configFilePath = $PSScriptRoot + "\DemoFile.cfg"
Write-Host $configFilePath

If I run DemoScript.ps1, you see $PSScriptRoot gets a value and correctly builds the config file path:

PS C:\Users\aaron> C:\TEMP\DemoScript\DemoScript.ps1
C:\TEMP\DemoScript\DemoFile.cfg

Now let’s move the DemoScript directory to C:\TEMP\NewRootFolder and run DemoScript.ps1 again. The config file path is built correctly to accommodate the file move.

PS C:\Users\aaron> C:\TEMP\NewRootFolder\DemoScript\DemoScript.ps1
C:\TEMP\NewRootFolder\DemoScript\DemoFile.cfg

This requires all  supporting files be in the same folder as the script or a child folder.

The old way: $MyInvocation.MyCommand.Path

I started on the SCCM packages prior to PowerShell 3.0, when $PSScriptRoot didn’t exist. Instead, we parsed the script path from another Automatic Variable, $MyInvocation.MyCommand.Path, and used it in the same fashion as $PSScriptRoot.

# DemoScript.ps1
$scriptPath = split-path -parent $MyInvocation.MyCommand.Path
$configFilePath = $scriptPath + "\DemoFile.cfg"
Write-Host $configFilePath
PS C:\Users\aaron> C:\TEMP\NewRootFolder\DemoScript\DemoScript.ps1
C:\TEMP\NewRootFolder\DemoScript\DemoFile.cfg

It works, but it requires an extra line of code and isn’t as simple as $PSScriptRoot, but it is an option on any legacy systems you may have that don’t have PowerShell 3.0.

Make your script resilient with $PSScriptRoot

Use $PSScriptRoot to build absolute file paths from relative ones to make your script and supporting files portable and resilient. As part of this, it is a good practice to create a new folder to become that common root when you start developing a new script that will have supporting files.

Reference

  • technet.microsoft.com
    • about_Automatic_Variables

General Automatic Variables

Reader Interactions

Comments

  1. C2016 says

    February 18, 2016 at 11:30 am

    Hello Aaron,
    First, I like your Beginner series! very informative. I have a question regarding copying security groups and distribution lists between users and security groups? Is there a mechanism to do this all at once? For example, If I want to copy all the group memberships of user A to security group B is that possible? or would I have to do it separately?

    Reply
    • Aaron says

      February 19, 2016 at 9:16 am

      Glad you like the post. More to come. Regarding your question, are you saying you want to return the group memberships of a user, and then add those groups as members to another security group?

  2. Ahmad yamout says

    April 27, 2017 at 4:35 am

    Hello dude I would like to appreciate your work . I have a question about how to get root folder directory that work for the latest powershell only 3+ , 4 and 5 .

    Reply
    • Aaron Rothstein says

      May 13, 2017 at 9:21 pm

      If you are working in 3.0 or later, use $PSScriptRoot. Did you have a more specific question I can help with?

  3. Ross says

    June 14, 2017 at 6:34 pm

    In your example, you show:

    $configFilePath = $PSScriptRoot + “\DemoFile.cfg”

    I expect you showed simple concatenation for ease of understanding, but any time you’re forming a path, I’d recommend using the Join-Path function:

    $configFilePath = Join-Path $PSScriptRoot “DemoFile.cfg”

    You won’t have to concern yourself with path delimiters (slash/backslash/wack/backwack).

    Reply
    • Aaron Rothstein says

      July 11, 2017 at 9:58 am

      Ross – thank you for pointing out that useful cmdlet! There is an example of where I had been using concatenation for so long I didn’t think to look to see if a better option had been implemented. I will be sure to use this going forward!

  4. Techie says

    September 21, 2017 at 1:15 pm

    Hello Thanks for the article,
    I would want to know if i write something like this in a script $srvlist = Import-Csv -Path ($PSScriptRoot + “\testvmlistupdated.csv”)
    which is placed in c:/user/xxx/Desktop/temp, would that mean powershell will import the the file from the folder where the script being excicuted?

    Reply
    • Aaron Rothstein says

      October 21, 2017 at 9:57 am

      Yes, that is correct. You will also see that your current working directory will change from whatever it was to the location of your script.

  5. RAFAEL says

    January 7, 2020 at 1:51 pm

    how i can goback one folder ? like this $PSScriptRoot\..\packages

    my $PSScriptRoot result is :C:\vs\xxx\yyy\Installer\InstallApp\InstallApp\silent

    but i want C:\vs\xxx\yyy\Installer\InstallApp\InstallApp\packages

    Reply
    • Aaron Rothstein says

      March 7, 2020 at 2:21 pm

      Hey Rafael,

      To get the parent path, you can do the following:
      (Get-Item $PSScriptRoot).Parent.FullName

      In your example, that will return C:\vs\xxx\yyy\Installer\InstallApp\InstallApp, and you can then concatenate “\packages” to build your desired path.

  6. Pramod Yadav says

    January 21, 2020 at 10:30 am

    This will help us refactor quite some scripts. Thank you for sharing!

    Reply

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Primary Sidebar

Aaron

Think PowerShell

Copyright © 2025 · Monochrome Pro on Genesis Framework · WordPress · Log in