Question

I want to merge script/function having multiple dot sourced scripts into single ps1 script/function. Each script that is included may also have its own includes and so on.

=== EDIT ===

I guess you need to be painfully obvious here on SO, so let me give trivial example:

first.ps1

. $PSScriptRoot\inc\second.ps1

"first"

second.ps1

"second"

Given the existence of function Merge that accepts main script and produces merged script:

Merge first.ps1 first-merged.ps1

the final script will look as:

first-merged.ps1

"second"
"first"

This is far from trivial to do given that you can dot source in bunch of different ways, for instance in a loop.

I suppose "powershell reader" will create something like this internally so perhaps there is a way to obtain it.

Was it helpful?

Solution

You're looking for something like the C preprocessor? That is, merge the contents without actually executing the script, right? AFAIK PowerShell doesn't delineate between dot sourcing and script execution. Dot sourcing is just another command. So you could either A) do a transitive search via regex of files that are dot sourced or if you're up for a challenge B) use the AST to help find dot sourced files e.g.:

(Get-Command .\first.ps1).ScriptBlock.Ast.EndBlock.Statements.PipelineElements  | Where InvocationOperator -eq Dot

Outputs:

CommandElements    : {$PSScriptRoot\second.ps1}
InvocationOperator : Dot
DefiningKeyword    :
DefinedKeywords    :
Redirections       : {}
Extent             : . $PSScriptRoot\second.ps1
Parent             : . $PSScriptRoot\second.ps1

And of course, you'd have to chase down all these dot sourced files to do the same to them (to achieve transitive closure). But as you mention, this can be challenging if say the path contains a variable that you don't know until runtime.

OTHER TIPS

You haven't specifically asked a question here, but I assume you meant to say "how do I do this". It is a very straightforward process.

For example, from Script1.ps1 (below) we can access functions in Script3.ps1 and Script4.ps1 by simply dot sourcing a single Script2.ps1 which contains these references.

Script1.ps1

.$PSScriptRoot\Script2.ps1

Get-Script3Name
Get-Script4Name

Script2.ps1

#dot source all the scripts you need access to
$PSScriptRoot\Script3.ps1
$PSScriptRoot\Script4.ps1

Script3.ps1

Function Get-Script3Name
{
    "This is Script3"
}

Script4.ps1

Function Get-Script4Name
{
    "This is Script4"
}

Results when running Script1.ps1

This is Script3
This is Script4

For more information, I also recommend reading this older post which has some very good answers provided

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top