mirror of
https://github.com/PowerShell/PowerShell
synced 2026-06-08 12:12:50 +00:00
[Feature] Fix Move-Item -Path with wildcard char (#7397)
Unescape non-literal, non-glob path in ProccessRecord and set the context.SuppressWildcardExpansion in RenameItem. This solve the issue where Rename-Item complains -Path does not exist when both -Path and CWD contains special characters.
This commit is contained in:
@@ -3225,7 +3225,7 @@ namespace Microsoft.PowerShell.Commands
|
||||
{
|
||||
if (base.SuppressWildcardExpansion)
|
||||
{
|
||||
MoveItem(path);
|
||||
MoveItem(path, literalPath: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -3234,173 +3234,165 @@ namespace Microsoft.PowerShell.Commands
|
||||
foreach (PathInfo resolvedPathInfo in resolvedPaths)
|
||||
{
|
||||
string resolvedPath = resolvedPathInfo.Path;
|
||||
MoveItem(resolvedPath);
|
||||
MoveItem(resolvedPath, literalPath: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // ProcessRecord
|
||||
}
|
||||
|
||||
private void MoveItem(string path)
|
||||
private void MoveItem(string path, bool literalPath = false)
|
||||
{
|
||||
CmdletProviderContext currentContext = CmdletProviderContext;
|
||||
currentContext.SuppressWildcardExpansion = literalPath;
|
||||
|
||||
do
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
string escapedPath = path;
|
||||
if (!base.SuppressWildcardExpansion) { escapedPath = WildcardPattern.Escape(path); }
|
||||
if (!InvokeProvider.Item.Exists(escapedPath, currentContext))
|
||||
{
|
||||
PSInvalidOperationException invalidOperation =
|
||||
(PSInvalidOperationException)
|
||||
PSTraceSource.NewInvalidOperationException(
|
||||
NavigationResources.MoveItemDoesntExist,
|
||||
path);
|
||||
|
||||
WriteError(
|
||||
new ErrorRecord(
|
||||
invalidOperation.ErrorRecord,
|
||||
invalidOperation));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
catch (PSNotSupportedException notSupported)
|
||||
{
|
||||
WriteError(
|
||||
new ErrorRecord(
|
||||
notSupported.ErrorRecord,
|
||||
notSupported));
|
||||
continue;
|
||||
}
|
||||
catch (DriveNotFoundException driveNotFound)
|
||||
{
|
||||
WriteError(
|
||||
new ErrorRecord(
|
||||
driveNotFound.ErrorRecord,
|
||||
driveNotFound));
|
||||
continue;
|
||||
}
|
||||
catch (ProviderNotFoundException providerNotFound)
|
||||
{
|
||||
WriteError(
|
||||
new ErrorRecord(
|
||||
providerNotFound.ErrorRecord,
|
||||
providerNotFound));
|
||||
continue;
|
||||
}
|
||||
catch (ItemNotFoundException pathNotFound)
|
||||
{
|
||||
WriteError(
|
||||
new ErrorRecord(
|
||||
pathNotFound.ErrorRecord,
|
||||
pathNotFound));
|
||||
continue;
|
||||
}
|
||||
|
||||
// See if the item to be moved is in use.
|
||||
bool isCurrentLocationOrAncestor = false;
|
||||
try
|
||||
{
|
||||
isCurrentLocationOrAncestor = SessionState.Path.IsCurrentLocationOrAncestor(path, currentContext);
|
||||
}
|
||||
catch (PSNotSupportedException notSupported)
|
||||
{
|
||||
WriteError(
|
||||
new ErrorRecord(
|
||||
notSupported.ErrorRecord,
|
||||
notSupported));
|
||||
continue;
|
||||
}
|
||||
catch (DriveNotFoundException driveNotFound)
|
||||
{
|
||||
WriteError(
|
||||
new ErrorRecord(
|
||||
driveNotFound.ErrorRecord,
|
||||
driveNotFound));
|
||||
continue;
|
||||
}
|
||||
catch (ProviderNotFoundException providerNotFound)
|
||||
{
|
||||
WriteError(
|
||||
new ErrorRecord(
|
||||
providerNotFound.ErrorRecord,
|
||||
providerNotFound));
|
||||
continue;
|
||||
}
|
||||
catch (ItemNotFoundException pathNotFound)
|
||||
{
|
||||
WriteError(
|
||||
new ErrorRecord(
|
||||
pathNotFound.ErrorRecord,
|
||||
pathNotFound));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isCurrentLocationOrAncestor)
|
||||
if (!InvokeProvider.Item.Exists(path, currentContext))
|
||||
{
|
||||
PSInvalidOperationException invalidOperation =
|
||||
(PSInvalidOperationException)
|
||||
PSTraceSource.NewInvalidOperationException(
|
||||
NavigationResources.MoveItemInUse,
|
||||
NavigationResources.MoveItemDoesntExist,
|
||||
path);
|
||||
|
||||
WriteError(
|
||||
new ErrorRecord(
|
||||
invalidOperation.ErrorRecord,
|
||||
invalidOperation));
|
||||
continue;
|
||||
}
|
||||
|
||||
// Default to the CmdletProviderContext that will direct output to
|
||||
// the pipeline.
|
||||
|
||||
CmdletProviderContext currentCommandContext = currentContext;
|
||||
currentCommandContext.PassThru = PassThru;
|
||||
|
||||
tracer.WriteLine("Moving {0} to {1}", path, Destination);
|
||||
|
||||
try
|
||||
{
|
||||
// Now do the move
|
||||
string escapedPath = path;
|
||||
if (!base.SuppressWildcardExpansion) { escapedPath = WildcardPattern.Escape(path); }
|
||||
InvokeProvider.Item.Move(escapedPath, Destination, currentCommandContext);
|
||||
}
|
||||
catch (PSNotSupportedException notSupported)
|
||||
{
|
||||
WriteError(
|
||||
new ErrorRecord(
|
||||
notSupported.ErrorRecord,
|
||||
notSupported));
|
||||
continue;
|
||||
}
|
||||
catch (DriveNotFoundException driveNotFound)
|
||||
{
|
||||
WriteError(
|
||||
new ErrorRecord(
|
||||
driveNotFound.ErrorRecord,
|
||||
driveNotFound));
|
||||
continue;
|
||||
}
|
||||
catch (ProviderNotFoundException providerNotFound)
|
||||
{
|
||||
WriteError(
|
||||
new ErrorRecord(
|
||||
providerNotFound.ErrorRecord,
|
||||
providerNotFound));
|
||||
continue;
|
||||
}
|
||||
catch (ItemNotFoundException pathNotFound)
|
||||
{
|
||||
WriteError(
|
||||
new ErrorRecord(
|
||||
pathNotFound.ErrorRecord,
|
||||
pathNotFound));
|
||||
continue;
|
||||
return;
|
||||
}
|
||||
}
|
||||
while (false);
|
||||
catch (PSNotSupportedException notSupported)
|
||||
{
|
||||
WriteError(
|
||||
new ErrorRecord(
|
||||
notSupported.ErrorRecord,
|
||||
notSupported));
|
||||
return;
|
||||
}
|
||||
catch (DriveNotFoundException driveNotFound)
|
||||
{
|
||||
WriteError(
|
||||
new ErrorRecord(
|
||||
driveNotFound.ErrorRecord,
|
||||
driveNotFound));
|
||||
return;
|
||||
}
|
||||
catch (ProviderNotFoundException providerNotFound)
|
||||
{
|
||||
WriteError(
|
||||
new ErrorRecord(
|
||||
providerNotFound.ErrorRecord,
|
||||
providerNotFound));
|
||||
return;
|
||||
}
|
||||
catch (ItemNotFoundException pathNotFound)
|
||||
{
|
||||
WriteError(
|
||||
new ErrorRecord(
|
||||
pathNotFound.ErrorRecord,
|
||||
pathNotFound));
|
||||
return;
|
||||
}
|
||||
|
||||
// See if the item to be moved is in use.
|
||||
bool isCurrentLocationOrAncestor = false;
|
||||
try
|
||||
{
|
||||
isCurrentLocationOrAncestor = SessionState.Path.IsCurrentLocationOrAncestor(path, currentContext);
|
||||
}
|
||||
catch (PSNotSupportedException notSupported)
|
||||
{
|
||||
WriteError(
|
||||
new ErrorRecord(
|
||||
notSupported.ErrorRecord,
|
||||
notSupported));
|
||||
return;
|
||||
}
|
||||
catch (DriveNotFoundException driveNotFound)
|
||||
{
|
||||
WriteError(
|
||||
new ErrorRecord(
|
||||
driveNotFound.ErrorRecord,
|
||||
driveNotFound));
|
||||
return;
|
||||
}
|
||||
catch (ProviderNotFoundException providerNotFound)
|
||||
{
|
||||
WriteError(
|
||||
new ErrorRecord(
|
||||
providerNotFound.ErrorRecord,
|
||||
providerNotFound));
|
||||
return;
|
||||
}
|
||||
catch (ItemNotFoundException pathNotFound)
|
||||
{
|
||||
WriteError(
|
||||
new ErrorRecord(
|
||||
pathNotFound.ErrorRecord,
|
||||
pathNotFound));
|
||||
return;
|
||||
}
|
||||
|
||||
if (isCurrentLocationOrAncestor)
|
||||
{
|
||||
PSInvalidOperationException invalidOperation =
|
||||
(PSInvalidOperationException)
|
||||
PSTraceSource.NewInvalidOperationException(
|
||||
NavigationResources.MoveItemInUse,
|
||||
path);
|
||||
|
||||
WriteError(
|
||||
new ErrorRecord(
|
||||
invalidOperation.ErrorRecord,
|
||||
invalidOperation));
|
||||
return;
|
||||
}
|
||||
|
||||
// Default to the CmdletProviderContext that will direct output to
|
||||
// the pipeline.
|
||||
|
||||
currentContext.PassThru = PassThru;
|
||||
|
||||
tracer.WriteLine("Moving {0} to {1}", path, Destination);
|
||||
|
||||
try
|
||||
{
|
||||
// Now do the move
|
||||
InvokeProvider.Item.Move(path, Destination, currentContext);
|
||||
}
|
||||
catch (PSNotSupportedException notSupported)
|
||||
{
|
||||
WriteError(
|
||||
new ErrorRecord(
|
||||
notSupported.ErrorRecord,
|
||||
notSupported));
|
||||
return;
|
||||
}
|
||||
catch (DriveNotFoundException driveNotFound)
|
||||
{
|
||||
WriteError(
|
||||
new ErrorRecord(
|
||||
driveNotFound.ErrorRecord,
|
||||
driveNotFound));
|
||||
return;
|
||||
}
|
||||
catch (ProviderNotFoundException providerNotFound)
|
||||
{
|
||||
WriteError(
|
||||
new ErrorRecord(
|
||||
providerNotFound.ErrorRecord,
|
||||
providerNotFound));
|
||||
return;
|
||||
}
|
||||
catch (ItemNotFoundException pathNotFound)
|
||||
{
|
||||
WriteError(
|
||||
new ErrorRecord(
|
||||
pathNotFound.ErrorRecord,
|
||||
pathNotFound));
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endregion Command code
|
||||
|
||||
|
||||
@@ -6,6 +6,10 @@ Describe "Move-Item tests" -Tag "CI" {
|
||||
Setup -f originalfile.txt -content "This is content"
|
||||
$source = "$TESTDRIVE/originalfile.txt"
|
||||
$target = "$TESTDRIVE/ItemWhichHasBeenMoved.txt"
|
||||
Setup -f [orig-file].txt -content "This is not content"
|
||||
$sourceSp = "$TestDrive/``[orig-file``].txt"
|
||||
$targetSpName = "$TestDrive/ItemWhichHasBeen[Moved].txt"
|
||||
$targetSp = "$TestDrive/ItemWhichHasBeen``[Moved``].txt"
|
||||
}
|
||||
It "Move-Item will move a file" {
|
||||
Move-Item $source $target
|
||||
@@ -13,6 +17,12 @@ Describe "Move-Item tests" -Tag "CI" {
|
||||
$target | Should -Exist
|
||||
"$target" | Should -FileContentMatchExactly "This is content"
|
||||
}
|
||||
It "Move-Item will move a file when path contains special char" {
|
||||
Move-Item $sourceSp $targetSpName
|
||||
$sourceSp | Should -Not -Exist
|
||||
$targetSp | Should -Exist
|
||||
$targetSp | Should -FileContentMatchExactly "This is not content"
|
||||
}
|
||||
|
||||
Context "Move-Item with filters" {
|
||||
BeforeAll {
|
||||
|
||||
Reference in New Issue
Block a user