From 4dc008045da73b0f1335376a8ece4fe2c702e0a6 Mon Sep 17 00:00:00 2001 From: KirtiRamchandani Date: Sun, 24 May 2026 19:57:33 +0530 Subject: [PATCH 1/3] Support Split-Path switches with LiteralPath --- .../commands/management/ParsePathCommand.cs | 55 ++++++++++++++++++- .../Split-Path.Tests.ps1 | 20 +++++++ 2 files changed, 72 insertions(+), 3 deletions(-) diff --git a/src/Microsoft.PowerShell.Commands.Management/commands/management/ParsePathCommand.cs b/src/Microsoft.PowerShell.Commands.Management/commands/management/ParsePathCommand.cs index ca616301ebb..357b6cfa9ef 100644 --- a/src/Microsoft.PowerShell.Commands.Management/commands/management/ParsePathCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Management/commands/management/ParsePathCommand.cs @@ -22,8 +22,14 @@ namespace Microsoft.PowerShell.Commands noQualifierSet, parentSet, qualifierSet, - literalPathSet})] - [OutputType(typeof(bool), ParameterSetName = new[] { isAbsoluteSet })] + literalPathSet, + literalPathLeafSet, + literalPathLeafBaseSet, + literalPathExtensionSet, + literalPathNoQualifierSet, + literalPathQualifierSet})] + [OutputType(typeof(bool), ParameterSetName = new[] { isAbsoluteSet, + literalPathIsAbsoluteSet })] public class SplitPathCommand : CoreCommandWithCredentialsBase { #region Parameters @@ -68,6 +74,36 @@ public class SplitPathCommand : CoreCommandWithCredentialsBase /// private const string literalPathSet = "LiteralPathSet"; + /// + /// The parameter set name to get the leaf name for LiteralPath. + /// + private const string literalPathLeafSet = "LiteralPathLeafSet"; + + /// + /// The parameter set name to get the leaf base name for LiteralPath. + /// + private const string literalPathLeafBaseSet = "LiteralPathLeafBaseSet"; + + /// + /// The parameter set name to get the extension for LiteralPath. + /// + private const string literalPathExtensionSet = "LiteralPathExtensionSet"; + + /// + /// The parameter set name to get the qualifier for LiteralPath. + /// + private const string literalPathQualifierSet = "LiteralPathQualifierSet"; + + /// + /// The parameter set name to get the noqualifier set for LiteralPath. + /// + private const string literalPathNoQualifierSet = "LiteralPathNoQualifierSet"; + + /// + /// The parameter set name to get the IsAbsolute set for LiteralPath. + /// + private const string literalPathIsAbsoluteSet = "LiteralPathIsAbsoluteSet"; + /// /// Gets or sets the path parameter to the command. /// @@ -83,7 +119,13 @@ public class SplitPathCommand : CoreCommandWithCredentialsBase /// /// Gets or sets the literal path parameter to the command. /// - [Parameter(ParameterSetName = "LiteralPathSet", Mandatory = true, ValueFromPipeline = false, ValueFromPipelineByPropertyName = true)] + [Parameter(ParameterSetName = literalPathSet, Mandatory = true, ValueFromPipeline = false, ValueFromPipelineByPropertyName = true)] + [Parameter(ParameterSetName = literalPathLeafSet, Mandatory = true, ValueFromPipeline = false, ValueFromPipelineByPropertyName = true)] + [Parameter(ParameterSetName = literalPathLeafBaseSet, Mandatory = true, ValueFromPipeline = false, ValueFromPipelineByPropertyName = true)] + [Parameter(ParameterSetName = literalPathExtensionSet, Mandatory = true, ValueFromPipeline = false, ValueFromPipelineByPropertyName = true)] + [Parameter(ParameterSetName = literalPathQualifierSet, Mandatory = true, ValueFromPipeline = false, ValueFromPipelineByPropertyName = true)] + [Parameter(ParameterSetName = literalPathNoQualifierSet, Mandatory = true, ValueFromPipeline = false, ValueFromPipelineByPropertyName = true)] + [Parameter(ParameterSetName = literalPathIsAbsoluteSet, Mandatory = true, ValueFromPipeline = false, ValueFromPipelineByPropertyName = true)] [Alias("PSPath", "LP")] public string[] LiteralPath { @@ -108,6 +150,7 @@ public string[] LiteralPath /// the PowerShell path. /// [Parameter(ParameterSetName = qualifierSet, Mandatory = true, ValueFromPipelineByPropertyName = true)] + [Parameter(ParameterSetName = literalPathQualifierSet, Mandatory = true, ValueFromPipelineByPropertyName = true)] public SwitchParameter Qualifier { get; set; } /// @@ -119,6 +162,7 @@ public string[] LiteralPath /// the PowerShell path. /// [Parameter(ParameterSetName = noQualifierSet, Mandatory = true, ValueFromPipelineByPropertyName = true)] + [Parameter(ParameterSetName = literalPathNoQualifierSet, Mandatory = true, ValueFromPipelineByPropertyName = true)] public SwitchParameter NoQualifier { get; set; } /// @@ -128,6 +172,7 @@ public string[] LiteralPath /// If true the parent of the path will be returned. /// [Parameter(ParameterSetName = parentSet, Mandatory = false, ValueFromPipelineByPropertyName = true)] + [Parameter(ParameterSetName = literalPathSet, Mandatory = false, ValueFromPipelineByPropertyName = true)] public SwitchParameter Parent { get; set; } = true; /// @@ -137,6 +182,7 @@ public string[] LiteralPath /// If true the leaf name of the path will be returned. /// [Parameter(ParameterSetName = leafSet, Mandatory = true, ValueFromPipelineByPropertyName = true)] + [Parameter(ParameterSetName = literalPathLeafSet, Mandatory = true, ValueFromPipelineByPropertyName = true)] public SwitchParameter Leaf { get; set; } /// @@ -146,6 +192,7 @@ public string[] LiteralPath /// If true the leaf base name of the path will be returned. /// [Parameter(ParameterSetName = leafBaseSet, Mandatory = true, ValueFromPipelineByPropertyName = true)] + [Parameter(ParameterSetName = literalPathLeafBaseSet, Mandatory = true, ValueFromPipelineByPropertyName = true)] public SwitchParameter LeafBase { get; set; } /// @@ -155,6 +202,7 @@ public string[] LiteralPath /// If true the extension of the path will be returned. /// [Parameter(ParameterSetName = extensionSet, Mandatory = true, ValueFromPipelineByPropertyName = true)] + [Parameter(ParameterSetName = literalPathExtensionSet, Mandatory = true, ValueFromPipelineByPropertyName = true)] public SwitchParameter Extension { get; set; } /// @@ -168,6 +216,7 @@ public string[] LiteralPath /// Determines if the path is an absolute path. /// [Parameter(ParameterSetName = isAbsoluteSet, Mandatory = true)] + [Parameter(ParameterSetName = literalPathIsAbsoluteSet, Mandatory = true)] public SwitchParameter IsAbsolute { get; set; } #endregion Parameters diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/Split-Path.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/Split-Path.Tests.ps1 index e34126b101f..e1da5dd510a 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/Split-Path.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/Split-Path.Tests.ps1 @@ -96,6 +96,26 @@ Describe "Split-Path" -Tags "CI" { Split-Path -Parent "\\server1\share1" | Should -BeExactly "${dirSep}${dirSep}server1" } + It "Should support parsing switches with LiteralPath" { + $literalDir = Join-Path -Path $TestDrive -ChildPath 'parent[dir]' + $literalPath = Join-Path -Path $literalDir -ChildPath 'child[file].txt' + $null = New-Item -ItemType Directory -Path $literalDir + $null = New-Item -ItemType File -Path $literalPath + + Split-Path -LiteralPath $literalPath -Parent | Should -BeExactly $literalDir + Split-Path -LiteralPath $literalPath -Leaf | Should -BeExactly 'child[file].txt' + Split-Path -LiteralPath $literalPath -LeafBase | Should -BeExactly 'child[file]' + Split-Path -LiteralPath $literalPath -Extension | Should -BeExactly '.txt' + Split-Path -LiteralPath $literalPath -Qualifier | Should -BeExactly (Split-Path -Path $literalPath -Qualifier) + Split-Path -LiteralPath $literalPath -NoQualifier | Should -BeExactly (Split-Path -Path $literalPath -NoQualifier) + Split-Path -LiteralPath $literalPath -IsAbsolute | Should -BeTrue + } + + It "Should reject conflicting parsing switches with LiteralPath" { + { Split-Path -LiteralPath TestDrive:\file.txt -Parent -Leaf -ErrorAction Stop } | + Should -Throw -ErrorId 'AmbiguousParameterSet,Microsoft.PowerShell.Commands.SplitPathCommand' + } + It 'Does not split a drive letter' { Split-Path -Path 'C:\' | Should -BeNullOrEmpty } From 1e833d42763ae245153c5784eb134ce1ee88736d Mon Sep 17 00:00:00 2001 From: KirtiRamchandani Date: Sun, 24 May 2026 20:06:38 +0530 Subject: [PATCH 2/3] Address Split-Path literal parameter set style --- .../commands/management/ParsePathCommand.cs | 52 +++++++++---------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/src/Microsoft.PowerShell.Commands.Management/commands/management/ParsePathCommand.cs b/src/Microsoft.PowerShell.Commands.Management/commands/management/ParsePathCommand.cs index 357b6cfa9ef..120e48f6c27 100644 --- a/src/Microsoft.PowerShell.Commands.Management/commands/management/ParsePathCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Management/commands/management/ParsePathCommand.cs @@ -22,14 +22,14 @@ namespace Microsoft.PowerShell.Commands noQualifierSet, parentSet, qualifierSet, - literalPathSet, - literalPathLeafSet, - literalPathLeafBaseSet, - literalPathExtensionSet, - literalPathNoQualifierSet, - literalPathQualifierSet})] - [OutputType(typeof(bool), ParameterSetName = new[] { isAbsoluteSet, - literalPathIsAbsoluteSet })] + literalPathSet})] + [OutputType(typeof(string), ParameterSetName = new[] { LiteralPathLeafSet })] + [OutputType(typeof(string), ParameterSetName = new[] { LiteralPathLeafBaseSet })] + [OutputType(typeof(string), ParameterSetName = new[] { LiteralPathExtensionSet })] + [OutputType(typeof(string), ParameterSetName = new[] { LiteralPathNoQualifierSet })] + [OutputType(typeof(string), ParameterSetName = new[] { LiteralPathQualifierSet })] + [OutputType(typeof(bool), ParameterSetName = new[] { isAbsoluteSet })] + [OutputType(typeof(bool), ParameterSetName = new[] { LiteralPathIsAbsoluteSet })] public class SplitPathCommand : CoreCommandWithCredentialsBase { #region Parameters @@ -77,32 +77,32 @@ public class SplitPathCommand : CoreCommandWithCredentialsBase /// /// The parameter set name to get the leaf name for LiteralPath. /// - private const string literalPathLeafSet = "LiteralPathLeafSet"; + private const string LiteralPathLeafSet = "LiteralPathLeafSet"; /// /// The parameter set name to get the leaf base name for LiteralPath. /// - private const string literalPathLeafBaseSet = "LiteralPathLeafBaseSet"; + private const string LiteralPathLeafBaseSet = "LiteralPathLeafBaseSet"; /// /// The parameter set name to get the extension for LiteralPath. /// - private const string literalPathExtensionSet = "LiteralPathExtensionSet"; + private const string LiteralPathExtensionSet = "LiteralPathExtensionSet"; /// /// The parameter set name to get the qualifier for LiteralPath. /// - private const string literalPathQualifierSet = "LiteralPathQualifierSet"; + private const string LiteralPathQualifierSet = "LiteralPathQualifierSet"; /// /// The parameter set name to get the noqualifier set for LiteralPath. /// - private const string literalPathNoQualifierSet = "LiteralPathNoQualifierSet"; + private const string LiteralPathNoQualifierSet = "LiteralPathNoQualifierSet"; /// /// The parameter set name to get the IsAbsolute set for LiteralPath. /// - private const string literalPathIsAbsoluteSet = "LiteralPathIsAbsoluteSet"; + private const string LiteralPathIsAbsoluteSet = "LiteralPathIsAbsoluteSet"; /// /// Gets or sets the path parameter to the command. @@ -120,12 +120,12 @@ public class SplitPathCommand : CoreCommandWithCredentialsBase /// Gets or sets the literal path parameter to the command. /// [Parameter(ParameterSetName = literalPathSet, Mandatory = true, ValueFromPipeline = false, ValueFromPipelineByPropertyName = true)] - [Parameter(ParameterSetName = literalPathLeafSet, Mandatory = true, ValueFromPipeline = false, ValueFromPipelineByPropertyName = true)] - [Parameter(ParameterSetName = literalPathLeafBaseSet, Mandatory = true, ValueFromPipeline = false, ValueFromPipelineByPropertyName = true)] - [Parameter(ParameterSetName = literalPathExtensionSet, Mandatory = true, ValueFromPipeline = false, ValueFromPipelineByPropertyName = true)] - [Parameter(ParameterSetName = literalPathQualifierSet, Mandatory = true, ValueFromPipeline = false, ValueFromPipelineByPropertyName = true)] - [Parameter(ParameterSetName = literalPathNoQualifierSet, Mandatory = true, ValueFromPipeline = false, ValueFromPipelineByPropertyName = true)] - [Parameter(ParameterSetName = literalPathIsAbsoluteSet, Mandatory = true, ValueFromPipeline = false, ValueFromPipelineByPropertyName = true)] + [Parameter(ParameterSetName = LiteralPathLeafSet, Mandatory = true, ValueFromPipeline = false, ValueFromPipelineByPropertyName = true)] + [Parameter(ParameterSetName = LiteralPathLeafBaseSet, Mandatory = true, ValueFromPipeline = false, ValueFromPipelineByPropertyName = true)] + [Parameter(ParameterSetName = LiteralPathExtensionSet, Mandatory = true, ValueFromPipeline = false, ValueFromPipelineByPropertyName = true)] + [Parameter(ParameterSetName = LiteralPathQualifierSet, Mandatory = true, ValueFromPipeline = false, ValueFromPipelineByPropertyName = true)] + [Parameter(ParameterSetName = LiteralPathNoQualifierSet, Mandatory = true, ValueFromPipeline = false, ValueFromPipelineByPropertyName = true)] + [Parameter(ParameterSetName = LiteralPathIsAbsoluteSet, Mandatory = true, ValueFromPipeline = false, ValueFromPipelineByPropertyName = true)] [Alias("PSPath", "LP")] public string[] LiteralPath { @@ -150,7 +150,7 @@ public string[] LiteralPath /// the PowerShell path. /// [Parameter(ParameterSetName = qualifierSet, Mandatory = true, ValueFromPipelineByPropertyName = true)] - [Parameter(ParameterSetName = literalPathQualifierSet, Mandatory = true, ValueFromPipelineByPropertyName = true)] + [Parameter(ParameterSetName = LiteralPathQualifierSet, Mandatory = true, ValueFromPipelineByPropertyName = true)] public SwitchParameter Qualifier { get; set; } /// @@ -162,7 +162,7 @@ public string[] LiteralPath /// the PowerShell path. /// [Parameter(ParameterSetName = noQualifierSet, Mandatory = true, ValueFromPipelineByPropertyName = true)] - [Parameter(ParameterSetName = literalPathNoQualifierSet, Mandatory = true, ValueFromPipelineByPropertyName = true)] + [Parameter(ParameterSetName = LiteralPathNoQualifierSet, Mandatory = true, ValueFromPipelineByPropertyName = true)] public SwitchParameter NoQualifier { get; set; } /// @@ -182,7 +182,7 @@ public string[] LiteralPath /// If true the leaf name of the path will be returned. /// [Parameter(ParameterSetName = leafSet, Mandatory = true, ValueFromPipelineByPropertyName = true)] - [Parameter(ParameterSetName = literalPathLeafSet, Mandatory = true, ValueFromPipelineByPropertyName = true)] + [Parameter(ParameterSetName = LiteralPathLeafSet, Mandatory = true, ValueFromPipelineByPropertyName = true)] public SwitchParameter Leaf { get; set; } /// @@ -192,7 +192,7 @@ public string[] LiteralPath /// If true the leaf base name of the path will be returned. /// [Parameter(ParameterSetName = leafBaseSet, Mandatory = true, ValueFromPipelineByPropertyName = true)] - [Parameter(ParameterSetName = literalPathLeafBaseSet, Mandatory = true, ValueFromPipelineByPropertyName = true)] + [Parameter(ParameterSetName = LiteralPathLeafBaseSet, Mandatory = true, ValueFromPipelineByPropertyName = true)] public SwitchParameter LeafBase { get; set; } /// @@ -202,7 +202,7 @@ public string[] LiteralPath /// If true the extension of the path will be returned. /// [Parameter(ParameterSetName = extensionSet, Mandatory = true, ValueFromPipelineByPropertyName = true)] - [Parameter(ParameterSetName = literalPathExtensionSet, Mandatory = true, ValueFromPipelineByPropertyName = true)] + [Parameter(ParameterSetName = LiteralPathExtensionSet, Mandatory = true, ValueFromPipelineByPropertyName = true)] public SwitchParameter Extension { get; set; } /// @@ -216,7 +216,7 @@ public string[] LiteralPath /// Determines if the path is an absolute path. /// [Parameter(ParameterSetName = isAbsoluteSet, Mandatory = true)] - [Parameter(ParameterSetName = literalPathIsAbsoluteSet, Mandatory = true)] + [Parameter(ParameterSetName = LiteralPathIsAbsoluteSet, Mandatory = true)] public SwitchParameter IsAbsolute { get; set; } #endregion Parameters From 8c629b7ef2705403260dc8f70f9ed70bcb914a58 Mon Sep 17 00:00:00 2001 From: KirtiRamchandani Date: Sun, 24 May 2026 20:14:13 +0530 Subject: [PATCH 3/3] Address Split-Path literal review feedback --- .../commands/management/ParsePathCommand.cs | 2 +- .../Microsoft.PowerShell.Management/Split-Path.Tests.ps1 | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Microsoft.PowerShell.Commands.Management/commands/management/ParsePathCommand.cs b/src/Microsoft.PowerShell.Commands.Management/commands/management/ParsePathCommand.cs index 120e48f6c27..5a7a82a2b4f 100644 --- a/src/Microsoft.PowerShell.Commands.Management/commands/management/ParsePathCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Management/commands/management/ParsePathCommand.cs @@ -95,7 +95,7 @@ public class SplitPathCommand : CoreCommandWithCredentialsBase private const string LiteralPathQualifierSet = "LiteralPathQualifierSet"; /// - /// The parameter set name to get the noqualifier set for LiteralPath. + /// The parameter set name to return the path without the qualifier for LiteralPath. /// private const string LiteralPathNoQualifierSet = "LiteralPathNoQualifierSet"; diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/Split-Path.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/Split-Path.Tests.ps1 index e1da5dd510a..333289021c6 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/Split-Path.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/Split-Path.Tests.ps1 @@ -99,16 +99,16 @@ Describe "Split-Path" -Tags "CI" { It "Should support parsing switches with LiteralPath" { $literalDir = Join-Path -Path $TestDrive -ChildPath 'parent[dir]' $literalPath = Join-Path -Path $literalDir -ChildPath 'child[file].txt' - $null = New-Item -ItemType Directory -Path $literalDir - $null = New-Item -ItemType File -Path $literalPath + [void][System.IO.Directory]::CreateDirectory($literalDir) + [System.IO.File]::WriteAllText($literalPath, '') Split-Path -LiteralPath $literalPath -Parent | Should -BeExactly $literalDir Split-Path -LiteralPath $literalPath -Leaf | Should -BeExactly 'child[file].txt' Split-Path -LiteralPath $literalPath -LeafBase | Should -BeExactly 'child[file]' Split-Path -LiteralPath $literalPath -Extension | Should -BeExactly '.txt' - Split-Path -LiteralPath $literalPath -Qualifier | Should -BeExactly (Split-Path -Path $literalPath -Qualifier) - Split-Path -LiteralPath $literalPath -NoQualifier | Should -BeExactly (Split-Path -Path $literalPath -NoQualifier) Split-Path -LiteralPath $literalPath -IsAbsolute | Should -BeTrue + Split-Path -LiteralPath env:PATH -Qualifier | Should -BeExactly 'env:' + Split-Path -LiteralPath env:PATH -NoQualifier | Should -BeExactly 'PATH' } It "Should reject conflicting parsing switches with LiteralPath" {