如何在R中检测远端文件夹中新添加的文件?

问题描述 投票:0回答:1

如何编写一个运行在服务器上的R脚本,在网络上检测远端文件夹中新添加的CSV文件(或其他特定格式),并自动下载?

文件夹的例子。https:/ftp.ncbi.nlm.nih.govpubpmc。

一旦在这个文件夹中添加了一个新的CSV文件,我想马上下载它在本地处理。

r http automation download detection
1个回答
4
投票

我知道OP在寻找一个 "事件监听器 "来监控文件服务器上的变化,但是... 一些 消息必须从远方的计算机上发送,以通知你的计算机有变化。如果你对文件服务器没有控制权,让它给你发消息的唯一方法就是先给它发一个请求。这意味着唯一可用的一般 "事件监听器 "是通过间歇性地轮询服务器来工作的。

根据你的轮询频率,这应该完全可以作为一个事件监听器来使用。打个比方,许多种类的蝙蝠通过发出间歇性的超声波脉冲并聆听响应来捕猎。这是一种间歇性轮询的形式,它的工作原理足以让它们活下去。

这确实意味着必须在自己的电脑上有某种软件在后台运行。你的两个选择是使用调度来间歇性地运行R脚本,或者在后台运行一个R脚本,在轮询之间暂停。

从评论中可以看出,OP只想下载任何一个 新的 文件添加到服务器上,但不是在程序第一次运行时创建现有文件的副本。这意味着必须在本地存储一个文件,列出上次检查时ftp目录的内容,然后将其与ftp目录的当前内容进行比较,并下载任何新文件以及更新内容记录。

这里有一个函数就是这样做的。第一次运行时,它会创建一个新的本地目录,以主机的url命名,并在目录中添加一个 .csv 文件,并列出该点的目录。之后对该函数的调用将比较本地和远程目录的内容,并下载任何新文件。

local_mirror <- function(url, root_dir = path.expand("~/"), silent = FALSE)
{
  if(substring(root_dir, nchar(root_dir), nchar(root_dir)) != "/")
    root_dir <- paste0(root_dir, "/")
  content <- rvest::html_nodes(xml2::read_html(url), "a")
  links <- rvest::html_attr(content, "href")
  links <- grep("/", links, invert = TRUE, value = TRUE)
  rel_path <- strsplit(url, "//")[[1]][2]
  mirror_path <- paste0(root_dir, rel_path)
  if(!dir.exists(mirror_path))
  {
    build_path <- root_dir
    for(i in strsplit(rel_path, "/")[[1]])
    {
      build_path <- paste0(build_path, i, "/")
      dir.create(build_path)
    }
    write.csv(links, paste0(mirror_path, ".mirrordat.csv"))
  }
  records <- read.csv(paste0(mirror_path, ".mirrordat.csv"), stringsAsFactors = FALSE)
  current_files <- records$x
  n_updated <- 0
  if(!silent) cat("Updating files - please wait")
  for(i in seq_along(links))
  {
    if(!(links[i] %in% current_files))
    {
      download.file(paste0(url, links[i]), paste0(mirror_path, links[i]))
      n_updated <- n_updated + 1
    }
  }
  if(!silent) message(paste("Downloaded", n_updated, "files"))
  write.csv(links, paste0(mirror_path, ".mirrordat.csv"))
}

要在你的情况下运行这个函数,你只需要运行:

local_mirror("https://ftp.ncbi.nlm.nih.gov/pub/pmc/")

如果要在后台作为一个持续的 "事件监测器 "运行它,你可以把它放在一个循环函数里面,比如这样:

listen_for_changes <- function(url, poll_every = 5, silent = TRUE)
{
  repeat
  {
    local_mirror(url, silent = silent)
    Sys.sleep(poll_every)
  }
}

你只要运行这个函数就可以了。

listen_for_changes("https://ftp.ncbi.nlm.nih.gov/pub/pmc/")

4
投票

我之前也遇到过类似的问题,我写了一个(有点)综合性的函数,叫做 repchkdl() 为此,我将其捆绑在一个小的 R 包。

这里是一个 联系 到其Github repo上。

它在很多方面都与@Allan Cameron建议的解决方案类似,并提供了额外的选项来微调远程URL的扫描方式(manualauto选项)、文件的下载方式(例如,用正则表达式过滤)以及迭代频率+限制(例如,每2分钟扫描一次,共重复两次,之后退出)等。

使用实例。

test <- repchkdl(inpurl = "ftp://speedtest.tele2.net/upload/", 
                 inpregex = ".txt$", autoscan = "y", autodl = "y", inpwait = 10,
                 scanlim = 2)

这将自动下载(autoscan = "y", autodl = "y") 所有以 .txt (inpregex = ".txt$")从URL ftp://speedtest.tele2.net/upload/,并每10秒检查一次更新 (inpwait = 10). 该函数将重新检查两次(scanlim = 2),然后退出。文件名的向量将被保存到对象的 test.

编辑。该包已被彻底改造,并有额外的功能,包括静音模式操作。仓库的位置仍然是 一样. 函数调用略有变化,如下所示(举例说明)。

test <- repchkdl(url = "ftp://ftp.swfwmd.state.fl.us/pub/usf/", 
                 usr = "anonymous", pwd = "[email protected]",
                 scanlim = 2, wait = 2, verbosity = TRUE)

head(test)
#                      flinks   fsizes dlstats
# 1        SWFWMD_May2020.txt 25321197 SUCCESS
# 2 USF_SCADA_AM_20200517.csv  2322041 SUCCESS
# 3 USF_SCADA_AM_20200518.csv  2321932 SUCCESS
# 4 USF_SCADA_AM_20200519.csv  2323118 SUCCESS
# 5 USF_SCADA_AM_20200520.csv  2322689 SUCCESS
# 6 USF_SCADA_AM_20200521.csv  2322243 SUCCESS
© www.soinside.com 2019 - 2024. All rights reserved.