Рекурсивно скачать фтп, затем извлечь файлы gz - PullRequest
3 голосов
/ 08 марта 2011

У меня есть многоэтапный процесс загрузки файлов, который я хотел бы выполнить в R. У меня есть средний шаг, но не первый и третий ...

# 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?

Ответы [ 3 ]

7 голосов
/ 08 марта 2011

Для части 1 может быть полезен RCurl. Функция getURL извлекает один или несколько URL; dirlistonly перечисляет содержимое каталога без извлечения файла. Остальная часть функции создает следующий уровень URL

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())
5 голосов
/ 08 марта 2011

Я могу прочитать содержимое страницы ftp, если запускаю R с опцией internet2.Т.е.

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

(Ярлык для запуска R в Windows можно изменить, добавив аргумент internet2 - щелкните правой кнопкой мыши / Properties / Target или просто запустите его в командной строке - и это очевидно в 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 все работает довольно легко.

Параметр internet2 был объяснен для аналогичного FTP-сайта здесь:

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

3 голосов
/ 15 июня 2012
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)
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...