Windows下R语言dir函数遇长文件名无法遍历全部文件的问题
Windows下R语言
dir函数处理长文件名时的文件遗漏问题解答 问题1:这是dir函数的预期行为还是bug?
这是bug,并非预期行为。
- Windows的260字符路径限制指的是Unicode字符数,而非字节数;
file.exists能正确识别该长文件名文件,说明R的文件系统底层可准确定位文件,但dir函数在遍历目录时遇到字节数超259的文件后会中断遍历,导致后续文件遗漏,甚至在R 4.2.2中直接崩溃,完全不符合函数应返回目录全部文件(或抛出明确错误)的设计预期。
问题2:如何检测或避免该问题?(可忽略长文件名文件)
检测方法
- 对比
dir返回的文件数量与目录实际文件数(可通过Windows资源管理器确认),若数量不符则可能存在该问题; - 使用
list.files(your_dir, full.names = TRUE)获取完整路径,通过nchar(enc2utf8(file_path))计算路径的UTF-8字节数,检查是否存在字节数接近/超过259的文件; - 用
fs::dir_info(your_dir)获取目录文件详情,对比返回结果的数量是否与实际一致。
避免方法
1. 使用fs包的dir_ls函数(推荐)
fs包是专门优化的文件系统操作工具,对Windows长文件名的兼容性更好,能完整遍历目录所有文件,不会出现中断问题:
install.packages("fs") fs::dir_ls("目标目录路径")
2. 修复system/shell命令的编码问题
调用Windows原生dir命令时,指定正确的编码参数即可解决Unicode字符乱码问题:
# 使用shell函数(Windows下更适配) shell("dir /B", intern = TRUE, encoding = "UTF-8") # 或使用system函数 system("dir /B", intern = TRUE, encoding = "UTF-8")
注:/B参数用于仅返回文件名,不含额外格式信息。
3. 保留reticulate调用Python的方案
若能接受少量模块导入开销,reticulate调用Python的os.listdir或os.scandir仍为可行方案,后者遍历效率更高:
library(reticulate) os <- import("os") os$listdir("目标目录路径")
4. 主动过滤长字节路径文件
若需要主动忽略长字节路径的文件,可先获取所有文件路径,再过滤掉字节数超标的项:
all_files <- list.files("目标目录路径", full.names = TRUE) # 计算UTF-8编码下的字节数,过滤掉超过259的文件 valid_files <- all_files[nchar(enc2utf8(all_files)) <= 259] # 若仅需要文件名,可进一步处理 valid_file_names <- basename(valid_files)
内容的提问来源于stack exchange,提问作者hmIto
相关产品推荐
相关产品推荐

