Skip to content

Commit caad7ed

Browse files
kwkamadityapatwardhan
authored andcommitted
Fix Rename-Item -Path with wildcard char (PowerShell#7398)
1 parent 4118fd2 commit caad7ed

4 files changed

Lines changed: 124 additions & 12 deletions

File tree

src/Microsoft.PowerShell.Commands.Management/commands/management/Navigation.cs

Lines changed: 72 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3519,22 +3519,87 @@ protected override bool ProviderSupportsShouldProcess
35193519

35203520
#region Command code
35213521

3522+
private Collection<PathInfo> GetResolvedPaths(string path)
3523+
{
3524+
Collection<PathInfo> results = null;
3525+
try
3526+
{
3527+
results = SessionState.Path.GetResolvedPSPathFromPSPath(path, CmdletProviderContext);
3528+
}
3529+
catch (PSNotSupportedException notSupported)
3530+
{
3531+
WriteError(
3532+
new ErrorRecord(
3533+
notSupported.ErrorRecord,
3534+
notSupported));
3535+
}
3536+
catch (DriveNotFoundException driveNotFound)
3537+
{
3538+
WriteError(
3539+
new ErrorRecord(
3540+
driveNotFound.ErrorRecord,
3541+
driveNotFound));
3542+
}
3543+
catch (ProviderNotFoundException providerNotFound)
3544+
{
3545+
WriteError(
3546+
new ErrorRecord(
3547+
providerNotFound.ErrorRecord,
3548+
providerNotFound));
3549+
}
3550+
catch (ItemNotFoundException pathNotFound)
3551+
{
3552+
WriteError(
3553+
new ErrorRecord(
3554+
pathNotFound.ErrorRecord,
3555+
pathNotFound));
3556+
}
3557+
3558+
return results;
3559+
}
3560+
35223561
/// <summary>
35233562
/// Moves the specified item to the specified destination
35243563
/// </summary>
35253564
protected override void ProcessRecord()
3565+
{
3566+
if (SuppressWildcardExpansion)
3567+
{
3568+
RenameItem(Path, literalPath: true);
3569+
return;
3570+
}
3571+
3572+
Collection<PathInfo> resolvedPaths = GetResolvedPaths(Path);
3573+
3574+
if (resolvedPaths == null)
3575+
{
3576+
return;
3577+
}
3578+
3579+
if (resolvedPaths.Count == 1)
3580+
{
3581+
RenameItem(resolvedPaths[0].Path, literalPath: true);
3582+
}
3583+
else
3584+
{
3585+
RenameItem(WildcardPattern.Unescape(Path), literalPath: true);
3586+
}
3587+
}
3588+
3589+
private void RenameItem(string path, bool literalPath = false)
35263590
{
35273591
CmdletProviderContext currentContext = CmdletProviderContext;
3592+
currentContext.SuppressWildcardExpansion = literalPath;
35283593

35293594
try
35303595
{
3531-
if (!InvokeProvider.Item.Exists(Path, currentContext))
3596+
if (!InvokeProvider.Item.Exists(path, currentContext))
35323597
{
35333598
PSInvalidOperationException invalidOperation =
35343599
(PSInvalidOperationException)
35353600
PSTraceSource.NewInvalidOperationException(
35363601
NavigationResources.RenameItemDoesntExist,
3537-
Path);
3602+
path);
35383603

35393604
WriteError(
35403605
new ErrorRecord(
@@ -3580,7 +3645,7 @@ protected override void ProcessRecord()
35803645
bool isCurrentLocationOrAncestor = false;
35813646
try
35823647
{
3583-
isCurrentLocationOrAncestor = SessionState.Path.IsCurrentLocationOrAncestor(_path, currentContext);
3648+
isCurrentLocationOrAncestor = SessionState.Path.IsCurrentLocationOrAncestor(path, currentContext);
35843649
}
35853650
catch (PSNotSupportedException notSupported)
35863651
{
@@ -3621,7 +3686,7 @@ protected override void ProcessRecord()
36213686
(PSInvalidOperationException)
36223687
PSTraceSource.NewInvalidOperationException(
36233688
NavigationResources.RenamedItemInUse,
3624-
Path);
3689+
path);
36253690

36263691
WriteError(
36273692
new ErrorRecord(
@@ -3635,12 +3700,12 @@ protected override void ProcessRecord()
36353700

36363701
currentContext.PassThru = PassThru;
36373702

3638-
tracer.WriteLine("Rename {0} to {1}", Path, NewName);
3703+
tracer.WriteLine("Rename {0} to {1}", path, NewName);
36393704

36403705
try
36413706
{
36423707
// Now do the rename
3643-
InvokeProvider.Item.Rename(Path, NewName, currentContext);
3708+
InvokeProvider.Item.Rename(path, NewName, currentContext);
36443709
}
36453710
catch (PSNotSupportedException notSupported)
36463711
{
@@ -3674,7 +3739,7 @@ protected override void ProcessRecord()
36743739
pathNotFound));
36753740
return;
36763741
}
3677-
} // ProcessRecord
3742+
}
36783743
#endregion Command code
36793744

36803745
} // RenameItemCommand

src/System.Management.Automation/namespaces/LocationGlobber.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -433,7 +433,13 @@ private Collection<PathInfo> ResolveDriveQualifiedPath(
433433

434434
s_pathResolutionTracer.WriteLine("Path is DRIVE-QUALIFIED");
435435

436-
string relativePath = GetDriveRootRelativePathFromPSPath(path, context, true, out drive, out providerInstance);
436+
string relativePath =
437+
GetDriveRootRelativePathFromPSPath(
438+
path,
439+
context,
440+
!context.SuppressWildcardExpansion,
441+
out drive,
442+
out providerInstance);
437443

438444
Dbg.Diagnostics.Assert(
439445
drive != null,

test/powershell/Modules/Microsoft.PowerShell.Management/FunctionProvider.Tests.ps1

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ Describe "Basic Function Provider Tests" -Tags "CI" {
104104
}
105105

106106
It "Fails to rename not existing function" {
107-
{ Rename-Item $nonExistingFunction -NewName $newName -ErrorAction Stop } | Should -Throw -ErrorId "InvalidOperation,Microsoft.PowerShell.Commands.RenameItemCommand"
107+
{ Rename-Item $nonExistingFunction -NewName $newName -ErrorAction Stop } | Should -Throw -ErrorId "PathNotFound,Microsoft.PowerShell.Commands.RenameItemCommand"
108108
}
109109

110110
It "Fails to rename function which is Constant" {
@@ -113,8 +113,8 @@ Describe "Basic Function Provider Tests" -Tags "CI" {
113113
}
114114

115115
It "Fails to rename function which is ReadOnly" {
116-
Set-Item $nonExistingFunction -Options "ReadOnly"
117-
{ Rename-Item $nonExistingFunction -NewName $newName -ErrorAction Stop } | Should -Throw -ErrorId "InvalidOperation,Microsoft.PowerShell.Commands.RenameItemCommand"
116+
Set-Item $nonExistingFunction -Options "ReadOnly" -Value $functionValue
117+
{ Rename-Item $nonExistingFunction -NewName $newName -ErrorAction Stop } | Should -Throw -ErrorId "CannotRenameFunction,Microsoft.PowerShell.Commands.RenameItemCommand"
118118
}
119119

120120
It "Renames ReadOnly function when -Force parameter is on" {

test/powershell/Modules/Microsoft.PowerShell.Management/Rename-Item.Tests.ps1

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,56 @@
22
# Licensed under the MIT License.
33
Describe "Rename-Item tests" -Tag "CI" {
44
BeforeAll {
5-
$content = "This is content"
65
Setup -f originalFile.txt -content "This is content"
76
$source = "$TESTDRIVE/originalFile.txt"
87
$target = "$TESTDRIVE/ItemWhichHasBeenRenamed.txt"
8+
Setup -f [orig-file].txt -content "This is not content"
9+
$sourceSp = "$TestDrive/``[orig-file``].txt"
10+
$targetSpName = "ItemWhichHasBeen[Renamed].txt"
11+
$targetSp = "$TestDrive/ItemWhichHasBeen``[Renamed``].txt"
12+
Setup -Dir [test-dir]
13+
$wdSp = "$TestDrive/``[test-dir``]"
914
}
1015
It "Rename-Item will rename a file" {
1116
Rename-Item $source $target
1217
test-path $source | Should -BeFalse
1318
test-path $target | Should -BeTrue
1419
"$target" | Should -FileContentMatchExactly "This is content"
1520
}
21+
It "Rename-Item will rename a file when path contains special char" {
22+
Rename-Item $sourceSp $targetSpName
23+
$sourceSp | Should -Not -Exist
24+
$targetSp | Should -Exist
25+
$targetSp | Should -FileContentMatchExactly "This is not content"
26+
}
27+
It "Rename-Item will rename a file when -Path and CWD contains special char" {
28+
$content = "This is content"
29+
$oldSpName = "[orig]file.txt"
30+
$oldSpBName = "``[orig``]file.txt"
31+
$oldSp = "$wdSp/$oldSpBName"
32+
$newSpName = "[renamed]file.txt"
33+
$newSp = "$wdSp/``[renamed``]file.txt"
34+
In $wdSp -Execute {
35+
$null = New-Item -Name $oldSpName -ItemType File -Value $content -Force
36+
Rename-Item -Path $oldSpBName $newSpName
37+
}
38+
$oldSp | Should -Not -Exist
39+
$newSp | Should -Exist
40+
$newSp | Should -FileContentMatchExactly $content
41+
}
42+
It "Rename-Item will rename a file when -LiteralPath and CWD contains special char" {
43+
$content = "This is not content"
44+
$oldSpName = "[orig]file2.txt"
45+
$oldSpBName = "``[orig``]file2.txt"
46+
$oldSp = "$wdSp/$oldSpBName"
47+
$newSpName = "[renamed]file2.txt"
48+
$newSp = "$wdSp/``[renamed``]file2.txt"
49+
In $wdSp -Execute {
50+
$null = New-Item -Name $oldSpName -ItemType File -Value $content -Force
51+
Rename-Item -LiteralPath $oldSpName $newSpName
52+
}
53+
$oldSp | Should -Not -Exist
54+
$newSp | Should -Exist
55+
$newSp | Should -FileContentMatchExactly $content
56+
}
1657
}

0 commit comments

Comments
 (0)