如何在R中通过CURL包优化SFTP服务器文件列表获取?
在R中使用curl包处理SFTP列表的问题
我正在R环境中尝试与SFTP服务器交互,选用了推荐的curl包(非RCurl)。目前已实现获取指定地址下目录/文件列表的基础代码:
# 创建新的curl句柄 han <- new_handle() # 设置SFTP选项 handle_setopt(han, verbose = TRUE) # 执行请求 result <- curl_fetch_memory(url = "{SFTP URL here}",handle = han) # 获取响应数据 response <- rawToChar(result$content)
注:该SFTP服务器无需密码,使用SFTP协议版本3
当前代码已能获取结果,但curl_fetch_memory返回的result$content包含文件名、日期、权限等所有信息,格式杂乱。我有两个问题:
- 能否自定义请求/句柄,获取类似SFTP服务器
ls命令的纯文件名列表? - 若无法自定义请求,是否有办法让CURL对象的输出更具可读性?
输出示例
response输出:
$url [1] "sftp://data.cyverse.org/shared/" $status_code [1] 0 $type [1] NA $headers raw(0) $modified [1] "2020-02-20 16:05:33 CST" $times redirect namelookup connect pretransfer starttransfer 0.000000 0.000029 0.000000 0.230600 0.000000 total 0.230608 $content [1] 64 72 77 78 72 2d 78 72 2d 78 20 20 20 20 31 20 30 20 20 20 20 20 20 20 20 [26] 30 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 30 20 44 65 63 20 33 31 20 [51] 20 31 39 36 39 20 2e 0a 64 72 77 78 72 2d 78 72 2d 78 20 20 20 20 31 20 30 [76] 20 20 20 20 20 20 20 20 30 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 30 [101] 20 44 65 63 20 33 31 20 20 31 39 36 39 20 2e 2e 0a 64 72 77 78 72 2d 78 72 [126] 2d 78 20 20 20 20 31 20 30 20 20 20 20 20 20 20 20 30 20 20 20 20 20 20 20 [151] 20 20 20 20 20 20 20 20 30 20 46 65 62 20 32 30 20 20 32 30 32 30 20 61 6c [176] 69 67 6e 6d 65 6e 74 73 5f 61 6e 64 5f 74 72 65 65 73 0a 64 72 77 78 72 2d [201] 78 72 2d 78 20 20 20 20 31 20 30 20 20 20 20 20 20 20 20 30 20 20 20 20 20 [226] 20 20 20 20 20 20 20 20 20 20 30 20 46 65 62 20 32 30 20 20 32 30 32 30 20 [251] 67 65 6e 65 5f 66 61 6d 69 6c 79 5f 65 76 6f 6c 75 74 69 6f 6e 0a 64 72 77 [276] 78 72 2d 78 72 2d 78 20 20 20 20 31 20 30 20 20 20 20 20 20 20 20 30 20 20 [301] 20 20 20 20 20 20 20 20 20 20 20 20 20 30 20 46 65 62 20 32 30 20 20 32 30 [326] 32 30 20 6d 61 70 73 5f 73 63 72 69 70 74 73 0a 64 72 77 78 72 2d 78 72 2d [351] 78 20 20 20 20 31 20 30 20 20 20 20 20 20 20 20 30 20 20 20 20 20 20 20 20 [376] 20 20 20 20 20 20 20 30 20 46 65 62 20 32 30 20 20 32 30 32 30 20 74 72 61 [401] 6e 73 63 72 69 70 74 5f 61 73 73 65 6d 62 6c 69 65 73 0a 64 72 77 78 72 2d [426] 78 72 2d 78 20 20 20 20 31 20 30 20 20 20 20 20 20 20 20 30 20 20 20 20 20 [451] 20 20 20 20 20 20 20 20 20 20 30 20 46 65 62 20 32 30 20 20 32 30 32 30 20 [476] 77 68 6f 6c 65 5f 67 65 6e 6f 6d 65 5f 64 75 70 6c 69 63 61 74 69 6f 6e 73 [501] 0a 2d 72 77 2d 72 2d 2d 72 2d 2d 20 20 20 20 31 20 30 20 20 20 20 20 20 20 [526] 20 30 20 20 20 20 20 20 20 20 20 20 20 20 20 36 36 39 20 4f 63 74 20 31 32 [551] 20 20 32 30 31 39 20 67 65 6e 65 5f 66 61 6d 69 6c 69 65 73 5f 6f 72 74 68 [576] 6f 66 69 6e 64 65 72 2e 74 78 74 0a 2d 72 77 2d 72 2d 2d 72 2d 2d 20 20 20 [601] 20 31 20 30 20 20 20 20 20 20 20 20 30 20 20 20 20 20 20 20 20 20 20 20 20 [626] 31 32 37 33 20 4f 63 74 20 31 32 20 20 32 30 31 39 20 72 65 61 64 6d 65 2e [651] 74 78 74 0a
result$content转成字符后输出:
'drwxr-xr-x 1 0 0 0 Dec 31 1969 .\ndrwxr-xr-x 1 0 0 0 Dec 31 1969 ..\ndrwxr-xr-x 1 0 0 0 Nov 7 2020 curated\n'
解决方案
问题1:获取纯文件名列表
curl本身没有直接配置让SFTP返回仅文件名的选项,因为SFTP协议的LIST命令默认返回包含权限、日期等的完整列表(类似ls -l的输出)。可以通过两种方式实现纯文件名提取:
方法1:发送SFTP的NAME命令
部分SFTP服务器支持NAME命令,可返回仅文件名的列表。通过handle_setopt的quote参数发送该命令:
han <- new_handle() # 发送NAME命令请求仅返回文件名 handle_setopt(han, quote = c("NAME")) result <- curl_fetch_memory(url = "sftp://data.cyverse.org/shared/", handle = han) filenames <- strsplit(rawToChar(result$content), "\n")[[1]] # 过滤空行 filenames <- filenames[filenames != ""] print(filenames)
注意:若服务器不支持NAME命令会返回错误,此时需用方法2。
方法2:从完整列表中提取文件名
通过字符串处理提取每行的最后一个字段作为文件名:
response <- rawToChar(result$content) # 按行分割并过滤空行、.和.. lines <- strsplit(response, "\n")[[1]] lines <- lines[lines != "" & !grepl("^\\.$|^\\.\\.$", lines)] # 提取每行最后一个字段 filenames <- sapply(lines, function(line) { parts <- strsplit(line, "\\s+")[[1]] parts[length(parts)] }) print(filenames)
问题2:让输出更具可读性
将返回的原始字符串解析为结构化数据框,方便查看和处理:
response <- rawToChar(result$content) lines <- strsplit(response, "\n")[[1]] lines <- lines[lines != "" & !grepl("^\\.$|^\\.\\.$", lines)] # 解析每行信息为数据框字段 parse_line <- function(line) { parts <- strsplit(line, "\\s+")[[1]] data.frame( permissions = parts[1], links = as.integer(parts[2]), owner = parts[3], group = parts[4], size = as.integer(parts[5]), date = paste(parts[6], parts[7], parts[8]), filename = parts[length(parts)], stringsAsFactors = FALSE ) } # 生成结构化数据框 file_info <- do.call(rbind, lapply(lines, parse_line)) print(file_info)
内容的提问来源于stack exchange,提问作者Sudoh
相关产品推荐
相关产品推荐

