Include relative files in PowerShell
Asked Answered
H

7

63

I would like to include script files with such pseudo syntax:

Include '.\scripA.ps1'

But the only thing I have found is some thing like this:

$thisScript = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent
. ($thisScript + '.\scriptA.ps1')

that is ugly.

Is there some nice way to include scripts with relative paths?

Highsounding answered 26/3, 2009 at 1:42 Comment(0)
M
8

Unfortunately no, there is no good way. PowerShell doesn't really support this idea very well at all in V1. Really the approach you are taking is the best approach

Multiplicity answered 26/3, 2009 at 1:44 Comment(5)
And what is about v2? Should I use Modules for external scripts and "Import-Module ./foo.psm1" syntax? Or any improvements for usual scripts inclusion?Highsounding
@alex2k8, i haven't done much work at all with V2 yet so I can't give too much help. I know that modules are supposed to be much more isolated than scripts but other than that I don't have much data.Multiplicity
In v2, you can use a module with a manifest that defines all modules, scripts, and even snapins/assemblies. A nice benefit of this is that you can have functions and variables that are private to the module.Nutty
Note: as of V2 you can easily reference include files, see my answer below.Regressive
In PowerShell 3.0 you can use . (Join-Path $PSScriptRoot settings.ps1) (command starting with a dot).Thermionic
I
130

You can utilize the $PSScriptRoot parameter like this:

. "$PSScriptRoot\script.ps1"
Indefatigable answered 26/11, 2013 at 11:42 Comment(1)
I found this really useful for Azure ARM template VM CustomScriptExtension where I was downloading several files from a storage account blob container using the FileUris parameter then calling one file which referenced the other files. Azure docs aren't very helpful in how to determine relative paths to the downloaded files. I was trying . .\path\to\script.ps1 which works when you run the script from Windows Explorer or a PS terminal in the same folder, but it kept failing on deployment to Azure. This answer solves the problem entirely.Hadden
O
30

You can dot-source (include) the file:

. .\scriptA.ps1

To get the full path of the script:

Resolve-Path .\scriptA.ps1

Olivero answered 26/3, 2009 at 9:45 Comment(3)
The first part does... but Resolve-Path will check the current directory and your path for the file. If your script directory is in your path ($env:path), it will find it.Calliper
Thnaks guys, I should have mention the cureent location.Olivero
Worked for me. Thanks +1Sterigma
E
21

Dot-sourcing is the simplest option albeit not particularly pretty, as already stated. However, this format makes it just a tad bit cleaner:

$ScriptDirectory = Split-Path $MyInvocation.MyCommand.Path
. (Join-Path $ScriptDirectory ScriptA.ps1)

Also, a note about relative paths that is useful to make explicit: the original post might seem to imply wanting a path relative to the current working directory; in reality the intention is to be relative to the current script's source directory (as alex2k8's own code sample indicates). Thus, this allows the current script to access other scripts from the same repository.

Everybody answered 2/6, 2011 at 17:19 Comment(0)
M
8

Unfortunately no, there is no good way. PowerShell doesn't really support this idea very well at all in V1. Really the approach you are taking is the best approach

Multiplicity answered 26/3, 2009 at 1:44 Comment(5)
And what is about v2? Should I use Modules for external scripts and "Import-Module ./foo.psm1" syntax? Or any improvements for usual scripts inclusion?Highsounding
@alex2k8, i haven't done much work at all with V2 yet so I can't give too much help. I know that modules are supposed to be much more isolated than scripts but other than that I don't have much data.Multiplicity
In v2, you can use a module with a manifest that defines all modules, scripts, and even snapins/assemblies. A nice benefit of this is that you can have functions and variables that are private to the module.Nutty
Note: as of V2 you can easily reference include files, see my answer below.Regressive
In PowerShell 3.0 you can use . (Join-Path $PSScriptRoot settings.ps1) (command starting with a dot).Thermionic
R
6

As of V2 (native starting with Win7/2008R2; see $psversiontable.psversion) you can easily include a file like so:

. "RelativeOrAbsolutePathToFile\include.ps1"

$result = FunctionInIncludeFile()

Reference:
How to reuse windows powershell functions in scripts

Regressive answered 22/3, 2013 at 9:5 Comment(2)
As far as I can tell, the problem with this is that the dot-source line is evaluated relative to the current working directory, rather than relative to the script that contains the dot-source line. So if you cd to the directory that contains the script first it works, but if you call it from another directory it doesn't.Chrysler
That's probably by design, thanks for the comment though mate!Regressive
B
2

You can use $PSScriptRoot and the "Split-Path" directive to make it work cleanly for relative paths. . (($PSScriptRoot | Split-Path | Split-Path)+'somedir\ps\script.ps1')

Bannerol answered 14/8, 2019 at 17:51 Comment(0)
R
0

This would probably work from any directory, but it'll be a sloooooowwwww find if your starting directory is not a direct antecedent directory of the file you're trying to include. IOW, if your starting point for this search is the root of c:\ or some other drive letter, this will probably be horrifically slow.

. $(Resolve-Path -literal $(gci -Recurse include.ps1))

This will work particularly well if you're developing scripts on your PC but need to deploy them to a server that's going to run the script as a scheduled task.

Ribbentrop answered 18/11, 2017 at 15:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.