functions/utility/Resolve-PSFPath.ps1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
function Resolve-PSFPath
{
<#
 .SYNOPSIS
  Resolves a path.
  
 .DESCRIPTION
  Resolves a path.
  Will try to resolve to paths including some basic path validation and resolution.
  Will fail if the path cannot be resolved (so an existing path must be reached at).
  
 .PARAMETER Path
  The path to validate.
  
 .PARAMETER Provider
  Ensure the path is of the expected provider.
  Allows ensuring one does not operate in the wrong provider.
  Common providers include the filesystem, the registry or the active directory.
  
 .PARAMETER SingleItem
  Ensure the path should resolve to a single path only.
  This may - intentionally or not - trip up wildcard paths.
  
 .PARAMETER NewChild
  Assumes one wishes to create a new child item.
  The parent path will be resolved and must validate true.
  The final leaf will be treated as a leaf item that does not exist yet.
  
 .EXAMPLE
  PS C:\> Resolve-PSFPath -Path report.log -Provider FileSystem -NewChild -SingleItem
  
  Ensures the resolved path is a FileSystem path.
  This will resolve to the current folder and the file report.log.
  Will not ensure the file exists or doesn't exist.
  If the current path is in a different provider, it will throw an exception.
  
 .EXAMPLE
  PS C:\> Resolve-PSFPath -Path ..\*
  
  This will resolve all items in the parent folder, whatever the current path or drive might be.
#>

    [CmdletBinding(HelpUri = 'https://psframework.org/documentation/commands/PSFramework/Resolve-PSFPath')]
    param (
        [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)]
        [string[]]
        $Path,
        
        [string]
        $Provider,
        
        [switch]
        $SingleItem,
        
        [switch]
        $NewChild
    )
    
    process
    {
        foreach ($inputPath in $Path)
        {
            if ($inputPath -eq ".")
            {
                $inputPath = (Get-Location).Path
            }
            if ($NewChild)
            {
                $parent = Split-Path -Path $inputPath
                $child = Split-Path -Path $inputPath -Leaf
                
                try
                {
                    if (-not $parent) { $parentPath = Get-Location -ErrorAction Stop }
                    else { $parentPath = Resolve-Path $parent -ErrorAction Stop }
                }
                catch { Stop-PSFFunction -Message "Failed to resolve path" -ErrorRecord $_ -EnableException $true -Cmdlet $PSCmdlet }
                
                if ($SingleItem -and (($parentPath | Measure-Object).Count -gt 1))
                {
                    Stop-PSFFunction -Message "Could not resolve to a single parent path!" -EnableException $true -Cmdlet $PSCmdlet
                }
                
                if ($Provider -and ($parentPath.Provider.Name -ne $Provider))
                {
                    Stop-PSFFunction -Message "Resolved provider is $($parentPath.Provider.Name) when it should be $($Provider)" -EnableException $true -Cmdlet $PSCmdlet
                }
                
                foreach ($parentItem in $parentPath)
                {
                    Join-Path $parentItem.ProviderPath $child
                }
            }
            else
            {
                try { $resolvedPaths = Resolve-Path $inputPath -ErrorAction Stop }
                catch { Stop-PSFFunction -Message "Failed to resolve path" -ErrorRecord $_ -EnableException $true -Cmdlet $PSCmdlet }
                
                if ($SingleItem -and (($resolvedPaths | Measure-Object).Count -gt 1))
                {
                    Stop-PSFFunction -Message "Could not resolve to a single parent path!" -EnableException $true -Cmdlet $PSCmdlet
                }
                
                if ($Provider -and ($resolvedPaths.Provider.Name -ne $Provider))
                {
                    Stop-PSFFunction -Message "Resolved provider is $($resolvedPaths.Provider.Name) when it should be $($Provider)" -EnableException $true -Cmdlet $PSCmdlet
                }
                
                $resolvedPaths.ProviderPath
            }
        }
    }
}