从 R 下载 Google Drive 目录中的所有文件和子目录

Del*_*eet 4 r

一些先前的相关问题1、2、3 ),但没有什么是我想要的,而且我无法让Jenny Bryan 在 2018 年发布的代码示例正常工作。

我有一个与我共享的文件夹,其中包含一些大文件。文件是嵌套的。所以我想递归到子目录并获取每个子目录中的所有文件。就我而言,只有两层,但如果有一种适用于任意数量层的方法就更好了。

最明显的尝试命令就是告诉它下载文件夹,希望它能找出子结构:

#load the libraries
library(tidyverse)
library(googledrive)

#folder link to id
#hidden for privacy reasons
jp_folder = "https://drive.google.com/drive/folders/XXXXX" 
folder_id = drive_get(as_id(jp_folder))

#download in entirety
drive_download(folder_id)
Run Code Online (Sandbox Code Playgroud)

不幸的是,这不起作用,因为它显然无法处理文件夹:

> drive_download(folder_id)
Error: Not a recognized Google MIME type:
  * application/vnd.google-apps.folder
Run Code Online (Sandbox Code Playgroud)

我尝试通过进入每个子目录来避免此问题:

#load the libraries
library(tidyverse)
library(googledrive)

#folder link to id
#hidden for privacy reasons
jp_folder = "https://drive.google.com/drive/folders/XXXXX" 

#get the id data frame
folder_id = drive_get(as_id(jp_folder))

#find files in folder
files = drive_ls(folder_id)

#loop dirs and download files inside them
for (i in seq_along(files$name)) {
  i_dir = drive_ls(files$id[i])
  
  #download files
  walk(i_dir$id, ~ drive_download(as_id(.x)))
}
Run Code Online (Sandbox Code Playgroud)

files对象看起来不错(用填充物替换字符串):

# A tibble: 6 x 3
  name   id                                drive_resource   
* <chr>  <chr>                             <list>           
1 A      AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA <named list [32]>
2 B      BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB <named list [32]>
3 C      CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC <named list [31]>
4 D      DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD <named list [31]>
5 E      EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE <named list [31]>
6 F      FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF <named list [31]>
Run Code Online (Sandbox Code Playgroud)

但是,当尝试获取子目录的内容时,会抛出以下错误:

> i_dir = drive_ls(files$id[i])
Error: 'path' does not identify at least one Drive file.
Run Code Online (Sandbox Code Playgroud)

这是怎么回事?

Del*_*eet 6

其实很简单:drive_ls()想要一个包含 1 行的数据框输入,而不是字符向量。该错误消息具有误导性(如果它只是告诉用户给它一个数据框,那就太好了)。如果将代码更改为该代码,并添加所需的循环,则可以自动下载子目录的内容。如果有子子目录,它将失败。需要在包中编写和实现适当的递归函数。

这段代码对我有用:

#load the libraries
library(stringr)
library(googledrive)
  
#folder link to id
jp_folder = "https://drive.google.com/drive/folders/XXXXX"
folder_id = drive_get(as_id(jp_folder))

#find files in folder
files = drive_ls(folder_id)

#loop dirs and download files inside them
for (i in seq_along(files$name)) {
  #list files
  i_dir = drive_ls(files[i, ])
  
  #mkdir
  dir.create(files$name[i])
  
  #download files
  for (file_i in seq_along(i_dir$name)) {
    #fails if already exists
    try({
      drive_download(
        as_id(i_dir$id[file_i]),
        path = str_c(files$name[i], "/", i_dir$name[file_i])
      )
    })
  }
}
Run Code Online (Sandbox Code Playgroud)

此版本会跳过已下载的文件。