It’s a simple one, but useful. And it can clean up some of your ugly scripts that have a lot of redundant paths embedded in strings.
# Reduced for the sake of the example
# The full advanced function is included at the end.
function Use-Location($Path, $Body) {
Push-Location $Path
try { &$Body }
finally { Pop-Location }
}
Usage of the function couldn’t be simpler and uses a C#-style scope syntax.
Use-Location "C:\Temp" {
mkdir textfiles
dir *.txt | move textfiles
mkdir images
dir *.jpg,*.png | move images
}
Obviously you could just as well use Push-Location and Pop-Location in a try/catch yourself but why? This way enforces clean scoping and ensures you don’t forget the call to pop.
##############################################################################
#.SYNOPSIS
# Executes a ScriptBlock within the context of the specified working directory.
#
#.DESCRIPTION
# This function sets the current location to the specified Path and executes a
# ScriptBlock. All relative paths in the ScriptBlock will be based on the new
# current directory. When the ScriptBlock exits, the old current directory
# will be restored.
#
#.PARAMETER Path
# The working directory to use for the duration of the ScriptBlock.
#
#.PARAMETER ScriptBlock
# The code to execute within the context of the new current directory.
#
#.PARAMETER Create
# Creates the directory if it does not exist.
#
#.EXAMPLE
# Use-Location "C:\Temp" {
#
# mkdir textfiles
# dir *.txt | move textfiles
#
# mkdir images
# dir *.jpg,*.png | move images
#
# }
#
#.LINK
# Push-Location
# Pop-Location
##############################################################################
function Use-Location {
[CmdletBinding()]
param(
[Alias('PSPath')]
[Alias('LiteralPath')]
[Parameter(Position=1, Mandatory=$true)]
[String]$Path,
[Parameter(Position=2, Mandatory=$true)]
[ScriptBlock]$ScriptBlock,
[Parameter()]
[Switch]$Create
)
$ErrorActionPreference = 'Stop'
# Create if necessary
if ($Create) {
$Exists = Test-Path -LiteralPath $Path -PathType Container
if (-not $Exists) {
New-Item $Path -ItemType Directory | Out-Null
}
}
Push-Location $Path -StackName 'Use-Location'
try { &$ScriptBlock }
finally { Pop-Location -StackName 'Use-Location' }
}

Posts
Great tip, very useful (also the use of try/finally is a good example of a self containing function).
2010-06-07 @ 3:52 am