如何通过R编程访问Windows「此电脑」无盘符相机文件
解决方案
相机在「此电脑」下无驱动器号,是因为默认采用MTP媒体传输协议挂载,不属于系统识别的块存储设备,常规Win32文件API、R原生的list.files/file.copy等函数无法直接访问,你查到的CLSID路径仅支持Windows Shell接口识别,无法直接作为文件路径传入R原生函数。
以下两种方案均可实现需求,优先推荐第一种,无需安装额外软件,全程可在R环境内完成操作。
方案1:R调用Windows Shell接口直接读写MTP设备(推荐)
通过RDCOMClient包调用Windows自带的Shell.ApplicationCOM对象,可直接枚举、复制MTP设备内的文件,不需要给相机分配盘符。
操作步骤
- 安装依赖包
# 安装用于调用系统COM接口的RDCOMClient包 install.packages("RDCOMClient")
- 复制以下函数到R环境,该函数会自动枚举连接的相机设备,按指定后缀筛选文件并增量复制到目标路径,自动跳过已存在的文件
copy_camera_files <- function(camera_name, target_path, file_ext = c("CR2", "CR3", "JPG", "JPEG", "MP4", "ARW", "NEF")) { library(RDCOMClient) shell <- COMCreate("Shell.Application") # 定位到「此电脑」对应的Shell命名空间 my_computer <- shell$Namespace("::{20D04FE0-3AEA-1069-A2D8-08002B30309D}") # 匹配已连接的相机设备 camera_item <- NULL for (i in 0:(my_computer$Items()$Count()-1)) { item <- my_computer$Items()$Item(i) if (item$Name() == camera_name) { camera_item <- item break } } if (is.null(camera_item)) stop("未找到对应名称的相机,请确认设备已连接、名称与资源管理器中显示的一致") # 递归遍历MTP目录的内部函数 traverse_and_copy <- function(folder, current_path = "") { folder_items <- folder$Items() for (i in 0:(folder_items$Count()-1)) { it <- folder_items$Item(i) rel_path <- file.path(current_path, it$Name()) if (it$IsFolder) { traverse_and_copy(it$GetFolder, rel_path) } else { ext <- toupper(tools::file_ext(it$Name())) if (ext %in% toupper(file_ext)) { local_dir <- file.path(target_path, dirname(rel_path)) dir.create(local_dir, recursive = TRUE, showWarnings = FALSE) local_file <- file.path(target_path, rel_path) if (!file.exists(local_file)) { target_ns <- shell$Namespace(normalizePath(local_dir)) # 参数设置:自动响应系统弹窗、不显示复制进度条 target_ns$CopyHere(it, 4|16) message("已复制: ", rel_path) } } } } } # 遍历相机下的所有存储分区(内置存储、SD卡) camera_root <- camera_item$GetFolder for (i in 0:(camera_root$Items()$Count()-1)) { storage <- camera_root$Items()$Item(i) if (storage$IsFolder) { message("正在扫描存储分区: ", storage$Name()) traverse_and_copy(storage$GetFolder) } } message("全部文件复制完成") }
- 调用函数:先打开文件资源管理器,确认相机显示的设备名称(比如
Canon EOS R6、SONY ILCE-7C),替换参数即可运行
# 调用示例 copy_camera_files( camera_name = "你的相机设备名", target_path = "D:/摄影素材/2024年6月拍摄", # 替换为你的本地/移动硬盘目标路径 file_ext = c("CR3", "JPG", "MP4") # 替换为你需要复制的文件后缀 )
注意事项
- 运行函数时不要手动干预系统弹出的复制提示,代码已配置自动响应规则
- 如果提示找不到设备,拔插USB线、重新打开相机电源后重试即可
方案2:将MTP相机映射为带盘符的本地驱动器
如果更习惯用R原生文件操作函数,可以用MTP盘符映射工具将相机挂载为普通盘符,挂载后相机路径和本地硬盘路径没有区别,可直接用list.files、file.copy等函数操作。
操作步骤
- 安装MTP盘符映射工具(这类工具为个人非商用免费软件,可直接搜索获取,比如MTPdrive)
- 打开工具,在设备列表选中已连接的相机,分配一个空闲盘符(比如
Z:) - 挂载完成后,即可用常规R代码实现文件复制,示例如下:
camera_path <- "Z:/" # 映射后的相机盘符 target_path <- "E:/移动硬盘备份/照片" # 递归获取所有符合后缀要求的文件 all_files <- list.files(camera_path, recursive = TRUE, full.names = TRUE) need_copy <- all_files[grepl("\\.(CR3|JPG|MP4)$", all_files, ignore.case = TRUE)] # 增量复制 for (f in need_copy) { target_file <- file.path(target_path, gsub("^[A-Z]:/", "", f)) dir.create(dirname(target_file), recursive = TRUE, showWarnings = FALSE) if (!file.exists(target_file)) file.copy(f, target_file) }
补充说明:直接拼接CLSID字符串作为文件路径无法被R识别的原因是,这类路径属于Shell虚拟路径,仅支持资源管理器、Shell COM接口解析,不兼容常规文件系统调用规则。
内容的提问来源于stack exchange,提问作者Filippo
相关产品推荐
相关产品推荐

