Fix FS moves across Unix mounts by rjmholt · Pull Request #13044 · PowerShell/PowerShell

That's very interesting. I did a small experiment with PS 7.1 and got this result though:

C:\Users\Robert Holt\Documents\Dev\Microsoft\PSScriptAnalyzer [implement-script-rules +4 ~9 -0 !]
> gi .\tools_copy\ | Sv t
C:\Users\Robert Holt\Documents\Dev\Microsoft\PSScriptAnalyzer [implement-script-rules +4 ~9 -0 !]
> $t.MoveTo('D:\tools')
MethodInvocationException: Exception calling "MoveTo" with "1" argument(s): "Source and destination path must have identical roots. Move will not work across volumes."
C:\Users\Robert Holt\Documents\Dev\Microsoft\PSScriptAnalyzer [implement-script-rules +4 ~9 -0 !]
> get-error

Exception             :
    Type           : System.Management.Automation.MethodInvocationException
    ErrorRecord    :
        Exception             :
            Type    : System.Management.Automation.ParentContainsErrorRecordException
            Message : Exception calling "MoveTo" with "1" argument(s): "Source and destination path
must have identical roots. Move will not work across volumes."
            HResult : -2146233087
        CategoryInfo          : NotSpecified: (:) [], ParentContainsErrorRecordException
        FullyQualifiedErrorId : IOException
        InvocationInfo        :
            ScriptLineNumber : 1
            OffsetInLine     : 1
            HistoryId        : -1
            Line             : $t.MoveTo('D:\tools')
            PositionMessage  : At line:1 char:1
                               + $t.MoveTo('D:\tools')
                               + ~~~~~~~~~~~~~~~~~~~~~
            CommandOrigin    : Internal
        ScriptStackTrace      : at <ScriptBlock>, <No file>: line 1
    TargetSite     :
        Name          : ConvertToMethodInvocationException
        DeclaringType : System.Management.Automation.ExceptionHandlingOps,
System.Management.Automation, Version=7.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
        MemberType    : Method
        Module        : System.Management.Automation.dll
    StackTrace     :
   at System.Management.Automation.ExceptionHandlingOps.ConvertToMethodInvocationException(Exception
exception, Type typeToThrow, String methodName, Int32 numArgs, MemberInfo memberInfo)
   at CallSite.Target(Closure , CallSite , Object , String )
   at System.Dynamic.UpdateDelegates.UpdateAndExecute2[T0,T1,TRet](CallSite site, T0 arg0, T1 arg1)
   at System.Management.Automation.Interpreter.DynamicInstruction`3.Run(InterpretedFrame frame)
   at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame
frame)
    Message        : Exception calling "MoveTo" with "1" argument(s): "Source and destination path
must have identical roots. Move will not work across volumes."
    Data           : System.Collections.ListDictionaryInternal
    InnerException :
        Type       : System.IO.IOException
        TargetSite :
            Name          : MoveTo
            DeclaringType : System.IO.DirectoryInfo
            MemberType    : Method
            Module        : System.IO.FileSystem.dll
        StackTrace :
   at System.IO.DirectoryInfo.MoveTo(String destDirName)
   at CallSite.Target(Closure , CallSite , Object , String )
        Message    : Source and destination path must have identical roots. Move will not work
across volumes.
        Source     : System.IO.FileSystem
        HResult    : -2146232800
    Source         : System.Management.Automation
    HResult        : -2146233087
CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
FullyQualifiedErrorId : IOException
InvocationInfo        :
    ScriptLineNumber : 1
    OffsetInLine     : 1
    HistoryId        : -1
    Line             : $t.MoveTo('D:\tools')
    PositionMessage  : At line:1 char:1
                       + $t.MoveTo('D:\tools')
                       + ~~~~~~~~~~~~~~~~~~~~~
    CommandOrigin    : Internal
ScriptStackTrace      : at <ScriptBlock>, <No file>: line 1

Personally I think user expectation will be for Move-Item to transparently deal with cross-volume moves without needing to specify a flag. mv doesn't require one and nor does .NET on Windows. Throwing an error is unhelpful and technically not performant -- it performs no useful work. I think the best way to get performance here is probably to optimise your mount layout.