如何在 Windows 的命令行上访问 MTP 设备?

如何在 Windows 的命令行上访问 MTP 设备?

大多数 MTP (媒体传输协议) 设备会以其设备名称或 GUID 显示在 Windows 文件资源管理器中,但并未分配驱动器号。

如何从命令行访问此类设备上的文件?使用 cmd.exe 或 PowerShell。

答案1

不幸的是,MTP 公开的 API 与普通文件系统 API 非常不同。因此,将 MTP 设备公开为读/写文件系统无法使用。主要原因:

维基百科

MTP 和 PTP 标准都不允许直接修改对象。相反,必须重新上传修改后的对象,这对于大型对象来说可能需要很长时间。使用 PTP/MTP 时,必须在开始阶段知道文件大小。

您的常用文件复制程序只会打开源文件和目标文件,然后将数据分块从源文件复制到目标文件。这不适用于 MTP,因为您需要使用 MTP 特殊函数,并且通用文件系统原语(读取、查找、写入)不可用。

还有其他限制。例如,MTP 设备上可同时读取或写入的文件数量受到严重限制。该设备的行为根本就不像文件系统。

我想只读用于 MTP 设备的文件系统驱动程序可能是可行的,但由于上述问题,它用处不大,所以没人愿意去创建它。

答案2

有一个专有的(但仍然很好)程序:MTP Drive(https://www.mtpdrive.com/) 允许您在 Windows 中将 MTP 设备“安装”为驱动器。虽然存在一些合理的限制,但它确实做得很好!

答案3

我已经成功安装了一个Garmin Descent Mk2i(与使用水下潜水日志) 使用 MTP 接口(一个开源项目)版本 9.18.0在 Windows 10 上。

这依赖于安装 Dokan(Dokany 1.5.1.1000),它公开了一个保险丝文件系统到 Windows 应用程序。

注 1:目前,MTPMount 的最新版本(19.8.0,如上链接)尚未更新,无法与最新的 v2.x Dokan 配合使用,您需要使用1.5.1.1000 Dokany 版本

注 2:MTPMount 是一个命令行应用程序,不会明确显示您需要输入的内容。
经过几分钟的失败尝试后,我发现下面的方法对我有用。

.\mtpmount-x64.exe mount "Descent Mk2i" "Primary"

答案4

如果 Android 手机在“文件传输”模式下确实使用 MTP 连接到 PC,那么 PowerShell 就是一个解决方案,我刚刚在 StackOverflow 上回答了这个问题:https://stackoverflow.com/a/75543733/3090890

下面是我在 StackOverflow 上回答的稍微编辑过的副本。

我找到了这个 PowerShell 脚本:https://github.com/nosalan/powershell-mtp-file-transfer/ 免责声明:我不是该脚本的作者,因此版权归他所有!为了回答这个问题,我从链接源中复制并粘贴了代码片段,以便提供一些解释。

访问手机的技巧如下:通过 USB 连接时,手机应处于“文件传输”模式:

$phoneName = "Nokia 7.2"    
$o = New-Object -com Shell.Application
$rootComputerDirectory = $o.NameSpace(0x11)
$phoneDirectory = $rootComputerDirectory.Items() | Where-Object {$_.Name -eq $phoneName} | select -First 1

然后你就可以遍历到你想要的目录:

$sourceFolder = $phoneDirectory
$phoneFolderName = "Internal shared storage\DCIM\Camera"
foreach($pathSegment in ($phoneFolderName -split "\\"))
{
    $sourceFolder = $sourceFolder.GetFolder.Items() | Where-Object {$_.Name -eq $pathSegment} | select -First 1
    if($sourceFolder -eq $null)
    {
      throw "Not found $phoneFolderName folder"
    }
}

最后将项目从到达的源文件夹复制到目标文件夹:

function Get-FullPathOfMtpDir($mtpDir)
{
    $fullDirPath = ""
    $directory = $mtpDir.GetFolder
    while($directory -ne $null)
    {
        $fullDirPath =  -join($directory.Title, '\', $fullDirPath)
        $directory = $directory.ParentFolder;
    }
    return $fullDirPath
}
$targetFolder = "E:\Test"
$destDirShell = (new-object -com Shell.Application).NameSpace($targetFolder)
$fullSourceDirPath = Get-FullPathOfMtpDir $sourceFolder 
foreach ($item in $sourceFolder.GetFolder.Items())
{
    $itemName = ($item.Name)
    $fullFilePath = Join-Path -Path $targetFolder -ChildPath $itemName

    if(Test-Path $fullFilePath)
    {
        Write-Host "Element '$itemName' already exists"
    }
    else
    {
        $copiedCount++;
        Write-Host ("Copying #{0}: {1}{2}" -f $copiedCount, $fullSourceDirPath, $item.Name)
        $destDirShell.CopyHere($item)
    }
}
Write-Host "Copied '$copiedCount' elements from '$fullSourceDirPath'"

也可以将文件复制回手机。这里我以交换目标和源为例,将“E:\Test\atestfileonpc.txt”复制到手机的“DCIM\Camera”文件夹中:

$sourceDirShell = (new-object -com Shell.Application).NameSpace($targetFolder)
$targetDirShell = $sourceFolder
$item = $sourceDirShell.Items() | Where-Object {$_.Name -eq "atestfileonpc.txt"} | select -First 1
targetDirShell.GetFolder.CopyHere($item)

相关内容