2011-03-08 50 views
2

我有一个多步骤的文件下载过程中,我想在R做我有中间的一步,但不是第一个和第三个......递归ftp下载,然后解压GZ文件

# STEP 1 Recursively find all the files at an ftp site 
# ftp://prism.oregonstate.edu//pub/prism/pacisl/grids 
all_paths <- #### a recursive listing of the ftp path contents??? #### 

# STEP 2 Choose all the ones whose filename starts with "hi" 
all_files <- sapply(sapply(strsplit(all_paths, "/"), rev), "[", 1) 
hawaii_log <- substr(all_files, 1, 2) == "hi" 
hi_paths <- all_paths[hawaii_log] 
hi_files <- all_files[hawaii_log] 

# STEP 3 Download & extract from gz format into a single directory 
mapply(download.file, url = hi_paths, destfile = hi_files) 
## and now how to extract from gz format? 
+0

行必须将其为R? HTTP最适合使用,但在FTP上并不完美。更通用的语言,比如Python,会更适合这类问题。 – chmullig 2011-03-08 02:35:41

+0

是的,我试图避免添加任何外部工具......现在我已经通过调用R的命令行wget做了一个解决方法,但是我希望能够将它作为一个独立的R传递给某个人脚本 – 2011-03-08 02:52:29

+0

只需复制和粘贴文本文件名并在一个循环中使用download.file就足够简单了 - 因此它为您的用户进行了硬编码,但仍然是独立的(或者您可以通过ftp进入站点和mget ...) – mdsumner 2011-03-08 03:02:09

回答

5

如果我用internet2选项启动R,我可以读取ftp页面的内容。即

C:\Program Files\R\R-2.12\bin\x64\Rgui.exe --internet2 

(在Windows上启动[R快捷键可以被修改,添加Internet2的参数 - 单击鼠标右键/属性/目标,或者只是运行在命令行 - 和明显的在GNU/Linux)。

该网页上的文字可以这样写:

download.file("ftp://prism.oregonstate.edu//pub/prism/pacisl/grids", "f.txt") 
txt <- readLines("f.txt") 

这一点更多的工作来解析出目录列表,然后读取它们递归的基础文件。

## (something like) 
dirlines <- txt[grep("Directory <A HREF=", txt)] 

## split and extract text after "grids/" 
split1 <- sapply(strsplit(dirlines, "grids/"), function(x) rev(x)[1]) 

## split and extract remaining text after "/" 
sapply(strsplit(split1, "/"), function(x) x[1]) 
[1] "dem" "ppt" "tdmean" "tmax" "tmin" 

这是关于这里,这似乎停止非常有吸引力,而且变得有点费力,所以我真的建议不同的选项。毫无疑问,使用RCurl可能会有更好的解决方案,并且我建议您学习使用ftp客户端和您的用户。命令行ftp,匿名登录和mget都很容易工作。

第二代互联网的选项是一个类似FTP站点说明如下:

https://stat.ethz.ch/pipermail/r-help/2009-January/184647.html

+0

第一部分是方便知道。除了启动选项,还有'setInternet2(TRUE)'。我认为子目录的递归函数是从那里做的一种方式,但至少现在我可以从页面获取文本。 – 2011-03-08 19:14:33

7

对于部分1,RCurl可能会有所帮助。 getURL函数检索一个或多个URL; dirlistonly列出目录的内容而不检索文件。该功能的其余部分创建网址的下一级

library(RCurl) 
getContent <- function(dirs) { 
    urls <- paste(dirs, "/", sep="") 
    fls <- strsplit(getURL(urls, dirlistonly=TRUE), "\r?\n") 
    ok <- sapply(fls, length) > 0 
    unlist(mapply(paste, urls[ok], fls[ok], sep="", SIMPLIFY=FALSE), 
      use.names=FALSE) 
} 

因此,与

dirs <- "ftp://prism.oregonstate.edu//pub/prism/pacisl/grids" 

开始,我们可以调用这个函数,寻找的东西,看起来像目录,一直持续到完成

fls <- character() 
while (length(dirs)) { 
    message(length(dirs)) 
    urls <- getContent(dirs) 
    isgz <- grepl("gz$", urls) 
    fls <- append(fls, urls[isgz]) 
    dirs <- urls[!isgz] 
} 

我们可以再使用getURL,但这次在fls(或fls的元素,在循环中)检索实际文件秒。或者,也许更好的打开一个URL连接,并使用gzcon来解压缩和处理文件。沿

con <- gzcon(url(fls[1], "r")) 
meta <- readLines(con, 7) 
data <- scan(con, integer()) 
+0

这不适合我:我得到一个'1''5'然后'错误在点[[1L]] [[1L]]:下标越界'我试图步骤:第一个'fls'分配大头针似乎并不是一个有效的目录,在urls的末尾有一个'\ r'。有趣的是,'dirlistonly'不会出现在'getURL()'帮助页面中。 – 2011-03-08 19:27:13

+1

我想在Windows上,strsplit应该是“\ r \ n *”。 RCurl依赖于系统库,可用的特定选项取决于所安装的库的版本。参见'listCurlOptions()';在Linux/MacOS上,可以使用'man curl_easy_setopt';不确定Windows。 – 2011-03-08 20:13:19

3
ftp.root <- where are the files 
dropbox.root <- where to put the files 

#===================================================================== 
# Function that downloads files from URL 
#===================================================================== 

fdownload <- function(sourcelink) { 

    targetlink <- paste(dropbox.root, substr(sourcelink, nchar(ftp.root)+1, 
nchar(sourcelink)), sep = '') 

    # list of contents 
    filenames <- getURL(sourcelink, ftp.use.epsv = FALSE, dirlistonly = TRUE) 
    filenames <- strsplit(filenames, "\n") 
    filenames <- unlist(filenames) 

    files <- filenames[grep('\\.', filenames)] 
    dirs <- setdiff(filenames, files) 
    if (length(dirs) != 0) { 
    dirs <- paste(sourcelink, dirs, '/', sep = '') 
    } 

    # files 
    for (filename in files) { 

    sourcefile <- paste(sourcelink, filename, sep = '') 
    targetfile <- paste(targetlink, filename, sep = '') 

    download.file(sourcefile, targetfile) 
    } 

    # subfolders 
    for (dirname in dirs) { 

    fdownload(dirname) 
    } 
} 
+0

来调用函数:fdownload(ftp.root) – 2012-06-15 18:30:12