In PowerShell, what is the difference between using dot (.
) and ampersand (&
) when invoking a cmdlet, function, script file, or operable program?
The difference between the .
and &
operators matters only when calling scripts or functions (or their aliases) - for cmdlets and external programs, they act the same.
For scripts and functions, .
and &
differ with respect to scoping of the definition of functions, aliases, and variables:
&, the call operator, executes scripts and functions in a child scope, which is the typical use case: functions and scripts are typically expected to execute without side effects:
The variables, (nested) functions, aliases defined in the script / function invoked are local to the invocation and go out of scope when the script exits / function returns.
Note, however, that even a script run in a child scope can affect the caller's environment, such as by using Set-Location
to change the current location, explicitly modifying the parent scope (Set-Variable -Scope 1 ...
) or the global scope ($global:...
) or defining process-level environment variables.
., the dot-sourcing operator, executes scripts and functions in the current scope and is typically used to modify the caller's scope by adding functions, aliases, and possibly variables for later use. For instance, this mechanism is used to load the $PROFILE
file that initializes an interactive session.
The caveat is that for functions (as opposed to scripts) the reference scope for child vs. current is not necessarily the caller's scope: if the function was defined in a module, the reference scope is that module's scope domain:
.
with a module-originated function is virtually pointless, because the scope getting modified is the module's.To segregate and give a clear understanding, I am explaining a scenario.
Imagine you have function named MyFunction
in a source.ps1
. And you wish to use that function in another script(MyCustomScript.ps1)
Put a line in MyCustomScript.ps1 like the below and you should be able to use it.
. path\of\the\source.ps1
MyFunction
So you are using the function which is present in source.ps1 in your custom script.
Whereas, &
is the call operator in Powershell which will help you to call any of the outside executable like psexec
and others.
Invoking a command (either directly or with the call operator) will create another scope known as child scope and will be gone once the command been executed. If the command is changing any of the values in a global variable then in that case the changes will be lost when the scope ends as well.
To avoid this drawback and to keep any changes made to global variables you can dot
the script which will always execute the script in your current scope.
Dot sourcing will only run the function or script within the current scope and call operator (&
) which will run a function or script as usual; but it will never add to the current scope.
Hope this gives an idea on when to use what.
You can also run things inside a module scope with the call operator, from my notes from Windows Powershell in Action.
# get and variable in module scope
$m = get-module counter
& $m Get-Variable count
& $m Set-Variable count 33
# see func def
& $m Get-Item function:Get-Count
# redefine func in memory
& $m {
function script:Get-Count
{
return $script:count += $increment * 2
}
}
# get original func def on disk
Import-Module .\counter.psm1 -Force
A few other things:
# run with commandinfo object
$d = get-command get-date
& $d
# call anonymous function
& {param($x,$y) $x+$y} 2 5
# same with dot operator
. {param($x,$y) $x+$y} 2 5
Like Mathias mentioned as a comment in this thread. &
is used to invoke the expression whatever comes after the &
and .
is used to invoke it in the current scope and is normally used to dot source a helper file which contains functions to make it available in callers scope.