google 驱动器文件复制的 6 分钟应用脚本限制的解决方法

Workaround to 6 minutes app script limits on google drive file copying

/**
 * Copies all the files in a folder to another one.
 */
function copyFolderContents_(source, target) {
  // Iterate files in source folder
  const filesIterator = source.getFiles()
  while (filesIterator.hasNext()) {
    const file = filesIterator.next()

    // Make a copy of the file keeping the same name
    file.makeCopy(file.getName(), target)
  }
}

/**
 * Recursivelly copies a folder and all its subfolders with all the files
 */
function copyFolder_(toCopy, copyInto) {
  // Makes the new folder (with the same name) into the `copyInto`
  const newFolder = copyInto.createFolder(toCopy.getName())

  // Copy the contents
  copyFolderContents_(toCopy, newFolder)

  // Iterate any subfolder
  const foldersIterator = toCopy.getFolders()
  while (foldersIterator.hasNext()) {
    const folder = foldersIterator.next()

    // Copy the folder and it's contents (recursive call)
    copyFolder_(folder, newFolder)
  }
}

/**
 * Entry point to execute with the Google Apps Script UI
 */
function copyFolder() {
  // Get the folders (by ID in this case)
  const toCopy = DriveApp.getFolderById('')
  const copyInto = DriveApp.getFolderById('')

  // Call the function that copies the folder
  copyFolder_(toCopy, copyInto)
}

此脚本在复制大文件夹时受到 6 分钟应用脚本限制。

如何解决这个问题?递归使得很难将文件分成几个部分并让 app-script 多次 运行 using this

我认为由于递归, 在简单的 for 循环中将要复制的文件夹和文件分开并使用 this 到 运行 不再可行,因为任务是相关的,如果 parents 则无法复制 child还没有。

唯一的解决方法是在一些数据库中建立一个树来记录帐户 A 中的等级制度, 并且树中的每个节点都标有标签“已复制”(如果脚本已考虑)。

每次脚本终止后,我们以 DFS 方式导航树以找到未完成的节点(文件或文件夹)

mongodb 最大支持 100 深度。应该可以捕获树。

正如所承诺的那样,这里 a fairly long and detailed answer 介绍了如何绕过最大脚本 运行 时间。

基础知识是:您需要正常退出,保存进度,设置触发器,根据需要重新运行多次,然后清理触发器和您保存进度的所有文件.

您可以使用 my answer here 加上类似于下面的门面的东西作为最快的方法,尽管可能比您想要的更复杂。

class DriveFacade {
  // drive functions facade

  static createFolder(parent, path) {
    // creates nested folders if they don't already exist
    let newFolder = parent
    let existsSoFar = true
    path.forEach(folderName => {
      if (existsSoFar) {
        const existingFolder = newFolder.getFoldersByName(folderName)
        if (existingFolder.hasNext()) {
          newFolder = existingFolder.next()
        } else {
          existsSoFar = false
        }
      }
      if (!existsSoFar) {
        newFolder = newFolder.createFolder(folderName)
      }
    })
    return newFolder
  }

  static createOrReplaceFile(parent, filename, content, mimeType) {
    const files = parent.getFilesByName(filename)
    if (files.hasNext()) {
      const file = files.next()
      if (file.getMimeType() === mimeType) {
        file.setContent(content)
        return file
      } else {
        file.setTrashed(true)
      }
    }
    return parent.createFile(filename, content, mimeType)
  }
}