fix(items): refuse to move a folder to another volume in Move-Item2
Windows can't move a folder to another volume. Move-Item2 moved folders
with CopyAllowed, so AlphaFS copied and deleted them instead: an empty
folder was deleted without being created at the destination, and a
folder with files failed with an error that named one of its files.
Folders now move without CopyAllowed, and the cmdlet writes a MoveError
with the category InvalidOperation that names the folder and the
destination, and leaves the folder in place. A file still moves to
another volume; with -Force, it keeps the error of Windows, (17).
The tests move to \\localhost\C$, which Windows treats as another volume,
and run only elevated.
Decision 22, item 6: an assumption in autopilot, flagged for the
maintainer's review.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
@ -24,7 +24,7 @@ The `Move-Item2` cmdlet moves the items in `-Path` to the location in `-Destinat
How `-Destination` is interpreted depends on what is already there. If the value names an existing folder, the cmdlet keeps the name of the source item and moves it into that folder. In every other case the value is the full path of the new item, which lets you move and rename in one step, or rename an item in place. `-Destination` is resolved against the current location once, when the cmdlet starts.
Without `-Force`, the cmdlet checks whether a file or folder already exists at the destination and writes a `DestinationFileAlreadyExists` error instead of overwriting it; the move itself then runs with the `CopyAllowed` option, which allows a file to move to a different volume. With `-WhatIf`, the cmdlet names an existing destination in a verbose message instead; before 5.0.0, it wrote the error also with `-WhatIf`. With `-Force`, the move runs with the `ReplaceExisting` option and overwrites an existing destination item. The folder that is to contain the moved item must exist; otherwise the cmdlet writes an error that names that folder, or, with `-WhatIf`, a verbose message.
Without `-Force`, the cmdlet checks whether a file or folder already exists at the destination and writes a `DestinationFileAlreadyExists` error instead of overwriting it; a file then moves with the `CopyAllowed` option, which allows it to move to a different volume. With `-WhatIf`, the cmdlet names an existing destination in a verbose message instead; before 5.0.0, it wrote the error also with `-WhatIf`. With `-Force`, the move runs with the `ReplaceExisting` option and overwrites an existing destination item. The folder that is to contain the moved item must exist; otherwise the cmdlet writes an error that names that folder, or, with `-WhatIf`, a verbose message.
The cmdlet supports `-WhatIf` and `-Confirm`, and it writes nothing to the pipeline unless you specify `-PassThru $true`.
@ -190,10 +190,12 @@ With `-PassThru $true` the cmdlet returns a folder object for each folder that i
Before 5.0.0, `-PassThru` also wrote the item when `-WhatIf` or a declined confirmation skipped the operation.
The cmdlet chooses between two mutually exclusive move options. Without `-Force` it moves with `CopyAllowed`, which permits a file to cross volume boundaries because Windows then copies and deletes it. With `-Force` it moves with `ReplaceExisting`, which overwrites the destination but does not request `CopyAllowed`, so a move across volumes can fail when `-Force` is specified. A folder can't move to another volume: the cmdlet writes a `MoveError`and leaves the folder in place, so copy it with `Copy-Item2` and remove it with `Remove-Item2` instead.
The cmdlet chooses between two mutually exclusive move options for a file. Without `-Force` it moves a file with `CopyAllowed`, which permits the file to cross volume boundaries because Windows then copies and deletes it. With `-Force` it moves with `ReplaceExisting`, which overwrites the destination but does not request `CopyAllowed`, so a file can't move to another volume when `-Force` is specified: the cmdlet writes the `MoveError` of Windows, "(17) The system cannot move the file to a different disk drive". A folder can't move to another volume at all: the cmdlet writes a `MoveError`with the category `InvalidOperation` that names the folder and the destination, and it leaves the folder in place, so copy it with `Copy-Item2` and remove it with `Remove-Item2` instead.
If a path in `-Path` does not exist, a file or folder exists at the destination and `-Force` is missing, or the folder that is to contain the moved item does not exist, the cmdlet writes a non-terminating error and continues with the next path. Before 5.0.0, it skipped the remaining paths that were passed in the same call. Before 5.0.0, it also reported an existing destination folder as a `MoveError`, and a missing destination folder as a `DirectoryNotFoundException` that named the source item ([#21](https://github.com/raandree/NTFSSecurity/issues/21)).
Before 5.0.0-rc7, a folder moved with `CopyAllowed` as well, so a move to another volume copied and deleted it: an empty folder was deleted without being created at the destination, and a folder with files failed with an error that named one of its files.
WriteVerbose(string.Format("Directory '{0}' moved to '{1}'",resolvedPath,actualDestination));
}
if(passThru)
WriteObject(item);
}
catch(NotSameDeviceExceptionex)
{
// A file gets here only with -Force, which moves without CopyAllowed; it keeps the error of Windows.
if(itemisDirectoryInfo)
{
varmessage=string.Format("The folder '{0}' can't move to another volume, '{1}'. Copy it with Copy-Item2, then remove it with Remove-Item2.",resolvedPath,actualDestination);
<maml:para>The `Move-Item2` cmdlet moves the items in `-Path` to the location in `-Destination`. It is the long-path counterpart of the built-in `Move-Item` cmdlet: it works through the AlphaFS library (`Alphaleonis.Win32.Filesystem`), so source and destination may be longer than the 260-character `MAX_PATH` limit. Files and folders can both be moved, and a folder is moved with everything it contains.</maml:para>
<maml:para>How `-Destination` is interpreted depends on what is already there. If the value names an existing folder, the cmdlet keeps the name of the source item and moves it into that folder. In every other case the value is the full path of the new item, which lets you move and rename in one step, or rename an item in place. `-Destination` is resolved against the current location once, when the cmdlet starts.</maml:para>
<maml:para>Without `-Force`, the cmdlet checks whether a file or folder already exists at the destination and writes a `DestinationFileAlreadyExists` error instead of overwriting it; the move itself then runs with the `CopyAllowed` option, which allows a file to move to a different volume. With `-WhatIf`, the cmdlet names an existing destination in a verbose message instead; before 5.0.0, it wrote the error also with `-WhatIf`. With `-Force`, the move runs with the `ReplaceExisting` option and overwrites an existing destination item. The folder that is to contain the moved item must exist; otherwise the cmdlet writes an error that names that folder, or, with `-WhatIf`, a verbose message.</maml:para>
<maml:para>Without `-Force`, the cmdlet checks whether a file or folder already exists at the destination and writes a `DestinationFileAlreadyExists` error instead of overwriting it; a file then moves with the `CopyAllowed` option, which allows it to move to a different volume. With `-WhatIf`, the cmdlet names an existing destination in a verbose message instead; before 5.0.0, it wrote the error also with `-WhatIf`. With `-Force`, the move runs with the `ReplaceExisting` option and overwrites an existing destination item. The folder that is to contain the moved item must exist; otherwise the cmdlet writes an error that names that folder, or, with `-WhatIf`, a verbose message.</maml:para>
<maml:para>The cmdlet supports `-WhatIf` and `-Confirm`, and it writes nothing to the pipeline unless you specify `-PassThru $true`.</maml:para>
<maml:para>`Move-Item2` moves through the AlphaFS library (`Alphaleonis.Win32.Filesystem`), which is why it handles source and destination paths that exceed the 260-character `MAX_PATH` limit of the built-in `Move-Item` cmdlet.</maml:para>
<maml:para>Before 5.0.0, `-PassThru` also wrote the item when `-WhatIf` or a declined confirmation skipped the operation.</maml:para>
<maml:para>The cmdlet chooses between two mutually exclusive move options. Without `-Force` it moves with `CopyAllowed`, which permits a file to cross volume boundaries because Windows then copies and deletes it. With `-Force` it moves with `ReplaceExisting`, which overwrites the destination but does not request `CopyAllowed`, so a move across volumes can fail when `-Force` is specified. A folder can't move to another volume: the cmdlet writes a `MoveError` and leaves the folder in place, so copy it with `Copy-Item2` and remove it with `Remove-Item2` instead.</maml:para>
<maml:para>The cmdlet chooses between two mutually exclusive move options for a file. Without `-Force` it moves a file with `CopyAllowed`, which permits the file to cross volume boundaries because Windows then copies and deletes it. With `-Force` it moves with `ReplaceExisting`, which overwrites the destination but does not request `CopyAllowed`, so a file can't move to another volume when `-Force` is specified: the cmdlet writes the `MoveError` of Windows, "(17) The system cannot move the file to a different disk drive". A folder can't move to another volume at all: the cmdlet writes a `MoveError` with the category `InvalidOperation` that names the folder and the destination, and it leaves the folder in place, so copy it with `Copy-Item2` and remove it with `Remove-Item2` instead.</maml:para>
<maml:para>If a path in `-Path` does not exist, a file or folder exists at the destination and `-Force` is missing, or the folder that is to contain the moved item does not exist, the cmdlet writes a non-terminating error and continues with the next path. Before 5.0.0, it skipped the remaining paths that were passed in the same call. Before 5.0.0, it also reported an existing destination folder as a `MoveError`, and a missing destination folder as a `DirectoryNotFoundException` that named the source item ( #21 (https://github.com/raandree/NTFSSecurity/issues/21)).</maml:para>
<maml:para>Before 5.0.0-rc7, a folder moved with `CopyAllowed` as well, so a move to another volume copied and deleted it: an empty folder was deleted without being created at the destination, and a folder with files failed with an error that named one of its files.</maml:para>