文件夹迭代器继续令牌递归循环

时间:2018-03-01 15:00:32

标签: google-apps-script

谢谢你们所有的帮助,因此在团队驱动器中设置这个递归循环。以下是我到目前为止的情况。我现在唯一的问题是我指定的Team Drive中有数万个文件夹。所以我认为我需要获得一个延续令牌来保持脚本运行超过6分钟。但是我完全不知道在脚本中获取或存储令牌的位置。我认为最简单的方法是每1-10次迭代运行一次令牌是安全的。以下是我目前的代码:

function generateFolderTree() {

  try {

    var rootFolder = DriveApp.getFolderById('xxxxxxxxxxxxxxx');
    var rootFolderName = rootFolder.getName();
    var rootsFolders = rootFolder.getFolders();

    //var ss = SpreadsheetApp.create("Emptyfolderslist"+ Math.floor(Date.now() / 1000));
    var ss = SpreadsheetApp.openById('xxxxxxxxxxxxxxxxxxxx');

    var sheet = ss.getSheets()[0];
    sheet.appendRow(["Parent Folder", "Folder URL", "Folder Name", "", "folder count", "file count"]);

    while( rootsFolders.hasNext()) {

      var currentFolder = rootsFolders.next()          
      var currentFolderFiles = currentFolder.getFiles();
      var currentFolderFolders = currentFolder.getFolders();
      var folderscount = 0;
      var filescount = 0;

      while( currentFolderFiles.hasNext()){
        filescount ++;
        currentFolderFiles.next();
      }

      while( currentFolderFolders.hasNext()){
        folderscount++;
        currentFolderFolders.next();
      }

      var path = '';
      var parentfldrs = currentFolder.getParents();
      while( parentfldrs.hasNext()) {
        path = path + " - " + parentfldrs.next().getName();
      }

      sheet.appendRow(["'============================="]);
      sheet.appendRow([path, currentFolder.getUrl(), currentFolder.getName(), "", folderscount, filescount]);

      getChildFolders(currentFolder, ss); 
    }
  } catch (e) {
    Logger.log(e.toString());
  }
}


function getChildFolders(aFolder, ss) {

  var childFolders = aFolder.getFolders();
  var filesInFolder = aFolder.getFiles();
  var sheet = ss.getSheets()[0];

  var foldercount = 0;
  var filecount = 0;
  var childFolder = '';
  var parentFolders = '';
  var loop = 0;

  while( childFolders.hasNext()){
    foldercount = 0;
    filecount = 0;
    childFolder = childFolders.next();

    var subFolders = childFolder.getFolders();
    var subFiles = childFolder.getFiles();

    while( subFolders.hasNext()) {
      foldercount++;
      subFolders.next();
    }

    while( subFiles.hasNext()) {
      filecount++;
      subFiles.next()
    }

    var parentfldrs = childFolder.getParents();

    while( parentfldrs.hasNext()) {
      parentFolders = parentfldrs.next().getName();
    }

    sheet.appendRow([parentFolders, childFolder.getUrl(), "'----", childFolder.getName(), foldercount, filecount]);

    getChildFolders(childFolder, ss);
  }
}

我在这里阅读了其他几个使用搜索的类似问题的链接,如下所示:

Google Apps Script: How to use ContinuationToken with recursive folder iterator

Google Apps Script To Copy Entire Google Drive File Structure; How To Avoid Timeouts?

2 个答案:

答案 0 :(得分:0)

在执行Google Apps脚本调用之间存储动态项目的唯一方法是使用PropertiesServiceCacheService。  通常在执行之间不会更改的静态项(例如电子表格ID或对特定CacheService的引用)可以安全地存储为全局变量。

如果您计划在几分钟/小时内使用延续令牌,我建议CacheService。如果您需要在超过6小时后保留延续令牌,则需要PropertiesService(因为6小时是放入后在CacheService中保留的最长时间)。

您需要添加程序逻辑,以便从循环中的任意点恢复。如果您确保只输入将在剩余时间内完成的循环 - 即将开始时间存储在变量(var start = new Date().getTime())中,并检查在您之前剩余的时间,则从任意点恢复将更容易开始一个新的循环(if (new Date().getTime() - start < someMaxDuration) {...})。如果没有足够的时间(例如1m,30s等),那么你应该保存状态并退出。如果你不保存状态并干净地退出,你重复数据,因为一些内部循环会重复。

最简单的开始是存储根级别迭代器的continuationToken,如您对链接问题的回答所做的那样:Google Apps Script To Copy Entire Google Drive File Structure; How To Avoid Timeouts?

...
while( rootFolders.hasNext() {
  // If more than 2/3 the execution time has been used, bail out.
  if( new Date().getTime() - start > 200 * 1000)
    return;

  ...

  getChildFolders(currentFolder, ss);

  // Store the continuation token for the maximum time (6h).
  if( rootFolders.hasNext())
    cache.put("ROOT_CONTINUE_TOKEN", rootFolders.getContinuationToken(), 21600);
  else
    cache.remove("ROOT_CONTINUE_TOKEN");
}
...

要恢复,您首先要检查该密钥的缓存/属性,如果不存在,则从头开始。您可能需要在缓存/属性中存储其他值(并且类似地使用存储的值):

var cache = CacheService.getScriptCache();
function generateFolderTree() {
  var cached = cache.get("someKey");
  var folderIterator;
  if(cached) {
    folderIterator = DriveApp.continueFolderIterator(cached);
    /* code for initializing a resumed iteration */
  }
  else {
    /* code for initializing an iteration from scratch */
  }

  /* code for iterating */
}

答案 1 :(得分:0)

如果要使用现成的模板,则可以将其用于递归文件夹和暂停/继续功能。请查看my answer来回答类似的问题。

基本上,这是通过存储对象数组来完成的,以便我们知道在每个文件夹迭代器和文件迭代器中恢复的位置。