Recursion 谷歌应用程序脚本复制整个谷歌驱动器文件结构;如何避免超时?

Recursion 谷歌应用程序脚本复制整个谷歌驱动器文件结构;如何避免超时?,recursion,google-apps-script,google-drive-api,session-timeout,Recursion,Google Apps Script,Google Drive Api,Session Timeout,我的组织正在切换到Google商业帐户,每个人都需要将其驱动器文件传输到新帐户。驱动器不允许在这些帐户之间转移所有权,因此我创建了一个脚本,将文件和文件夹从旧帐户复制到新帐户。(旧帐户的内容已移动到与新帐户共享的文件夹中。) 以下是我目前掌握的情况: function copyDrive() { var originFolder = DriveApp.getFolderById(originFolderID); var destination = DriveApp.getFolderBy

我的组织正在切换到Google商业帐户,每个人都需要将其驱动器文件传输到新帐户。驱动器不允许在这些帐户之间转移所有权,因此我创建了一个脚本,将文件和文件夹从旧帐户复制到新帐户。(旧帐户的内容已移动到与新帐户共享的文件夹中。)

以下是我目前掌握的情况:

function copyDrive() {
  var originFolder = DriveApp.getFolderById(originFolderID);
  var destination = DriveApp.getFolderById(destinationID);
  copyFiles(originFolder, destination);

};

function copyFiles(passedFolder, targetFolder) {
  var fileContents = passedFolder.getFiles();
  var file;
  var fileName;

  while(fileContents.hasNext()) {
    file = fileContents.next();
    fileName = file.getName();
    file.makeCopy(fileName, targetFolder);
  }
  copySubFolders(passedFolder, targetFolder);
};

function copySubFolders(passedFolder, targetFolder) {
  var folderContents = passedFolder.getFolders();
  var folder;
  var folderName;

  while(folderContents.hasNext()) {
    folder = folderContents.next();
    folderName = folder.getName();
    var subFolderCopy = targetFolder.createFolder(folderName);
    copyFiles(folder, subFolderCopy);
  }
};
请原谅任何不雅行为;这方面我是新手。该脚本实际上工作得很好,并保留了文件夹结构,但在复制约150个文件和文件夹后超时。我一直在研究如何使用延续标记,我已经仔细阅读了。我认为我停留在概念层面,因为我不确定延续标记将如何与我设置的递归函数交互。看起来我最终会得到一堆我的
copySubFolders
函数,它们都需要自己的延续令牌。当然,它们的迭代器都使用相同的变量名,所以我真的不知道如何设置它


有什么想法吗?很抱歉发布这样一个无助的新手问题;我希望这至少对某些人来说是一个有趣的问题。

我知道您希望使用一种简单的编程方式来实现这一点,但安装Google Drive for Desktop并让他们右键单击、复制和粘贴可能是最简单的

这个想法:

  • 创建一个文件夹,用户将其驱动器的每一项都放在其中。(我看你已经这么做了。)
  • 与他们的新帐户共享该文件夹。(我看你也已经这么做了。)
  • 使用桌面驱动器登录他们的新帐户
  • 复制桌面驱动器中的文件夹并将其粘贴回。所有权转移到新帐户
    只是一个想法

    我想我已经解决了概念上的问题,尽管我越来越

    很抱歉,发生了服务器错误。请稍等,然后重试。(第9行,文件“代码”)

    当我尝试执行它时

    基本上,我将它设置为一次只复制一个顶级文件夹,对于其中的每一个,它都使用我以前使用的递归函数。它应该为第一级文件夹和根文件夹中的任何文件保存继续标记,以便在下一次执行时从停止的地方继续执行。这样,我的递归函数堆栈中就不涉及令牌了

    function copyDrive() {
    
    
      var originFolder = DriveApp.getFolderById(originFolderID);
      var destination = DriveApp.getFolderById(destinationID);
    
      var scriptProperties = PropertiesService.getScriptProperties();
      var fileContinuationToken = scriptProperties.getProperty('FILE_CONTINUATION_TOKEN');
      var fileIterator = fileContinuationToken == null ?
        originFolder.getFiles() : DriveApp.continueFileIterator(fileContinuationToken);
      var folderContinuationToken = scriptProperties.getProperty('FOLDER_CONTINUATION_TOKEN');
      var folderIterator = folderContinuationToken == null ?
        originFolder.getFolders() : DriveApp.continueFolderIterator(folderContinuationToken);
    
      try {
        var rootFileName;
        while(fileIterator.hasNext()) {
          var rootFile = fileIterator.next();
          rootFileName = rootFile.getName();
          rootFile.makeCopy(rootFileName, destination);
          }
    
        var folder = folderIterator.next();
        var folderName = folder.getName();
        var folderCopy = folder.makeCopy(folderName, destination);
    
    
        copyFiles(folder, folderCopy);
    
      } catch(err) {
        Logger.log(err);
      }
    
      if(fileIterator.hasNext()) {
        scriptProperties.setProperty('FILE_CONTINUATION_TOKEN', fileIterator.getContinuationToken());
      } else {
        scriptProperties.deleteProperty('FILE_CONTINUATION_TOKEN');
      }
      if(folderIterator.hasNext()) {
        scriptProperties.setProperty('FOLDER_CONTINUATION_TOKEN', folderIterator.getContinuationToken());
      } else {
        scriptProperties.deleteProperty('FOLDER_CONTINUATION_TOKEN');
      }
    
    };
    
    function copyFiles(passedFolder, targetFolder) {
      var fileContents = passedFolder.getFiles();
      var file;
      var fileName;
    
      while(fileContents.hasNext()) {
        file = fileContents.next();
        fileName = file.getName();
        file.makeCopy(fileName, targetFolder);
      }
      copySubFolders(passedFolder, targetFolder);
    };
    
    function copySubFolders(passedFolder, targetFolder) {
      var subFolderContents = passedFolder.getFolders();
      var subFolder;
      var subFolderName;
    
      while(folderContents.hasNext()) {
        subFolder = subFolderContents.next();
        subFolderName = subFolder.getName();
        var subFolderCopy = targetFolder.createFolder(folderName);
        copyFiles(subFolder, subFolderCopy);
      }
    };
    

    您需要存储文件夹迭代器和文件迭代器的数组,因为每个文件夹都可能有一个嵌套的文件夹数组。如果重复使用与已接受解决方案中相同的文件夹迭代器,则无法在更多顶级文件夹上继续


    在这里查看一个模板,您可以使用该模板递归迭代内置恢复功能的驱动器中的所有文件。

    有些问题会处理类似的问题。要开始,您需要的关键部分是触发器。你可以有一个5分钟的重复触发,它将尽可能多地处理,并以某种方式记住它在哪里,以便下一个触发继续它停止的地方。您可以使用脚本属性存储位置。这不是小事,而是doable@ZigMandel触发器是微不足道的,也不是真正必要的。我能够告诉脚本重复执行,直到它完成,我不认为它会运行我们的大多数用户很多次。我知道存储位置的方法是将“continuation token”保存为脚本属性,但我的问题是如何使这些token与我创建的递归函数正常工作。这部分有意义吗?它将在6分钟后超时,所以如果你不使用触发器,它将失败,除非你有几个文件。如果问题是关于使用延续令牌的问题,请发布您尝试使用它们的代码。触发器不会阻止它失败;他们只会定期重启。我没有带令牌的代码,因为我需要解决如何使用令牌的问题。我包括了一个链接,指向一个确实使用它们的项目。当我有一个完整的调用堆栈时,我将有多个文件夹迭代器在进行中,所有这些迭代器都命名为folderContents。如果我想停止脚本并能够从我停止的地方开始,我必须为函数的每个实例保存一个不同的延续令牌,并找出如何使堆栈再次运行,并为每个级别分配正确的令牌。有意义吗?你可以试试我的文件夹复印表加载项。如果您有想法让它更强大,我一直在寻找合作伙伴帮助开发它。我同意使用桌面驱动器应该是一个简单的解决方案,但有几个人报告说安装后会出现严重的崩溃。我不知道为什么会发生这样的事情,我也不太可能弄清事情的真相。我不在里面或者别的什么;我只是一个随机的员工,他认为自己能帮上忙。除非你不介意你的谷歌文件(SorReadsheets、docs等)不会被复制,否则这是行不通的。比尔,我理解你的情况。你最初的问题很有道理,关于如何避免超时。我会继续研究解决这个问题的办法。Zig,这对Google文件非常有效。我已经做了一段时间了。为什么你认为不会呢?谢谢通用汽车!Zig,这确实适用于Google文件,正如我在原始问题中提到的。酷。Om惊讶地发现,这适用于像电子表格这样的google文件。我通过手动删除脚本属性解决了上述错误。不过,现在,为文件夹迭代器保存的延续标记在末尾与从脚本属性加载的延续标记在开头是相同的。我不知道为什么会这样,我想这仍然符合最初的问题。干得好!看起来它要求
    等待一点
    ,因为。脚本已达到每个用户每100秒1000次查询的限制,或者已达到总天数配额。您可以
    睡眠