You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为无超时遍历Drive的Google App Script添加文件复制功能

Google Apps Script 无超时遍历并复制文件夹文件改造方案

已有一段可无超时遍历指定根文件夹所有文件及子文件夹的Google Apps Script代码,需改造processFile函数,实现将遍历到的所有文件复制到目标文件夹。以下是具体改造方案:

改造步骤

  1. 新增目标文件夹配置:在入口函数中添加目标文件夹获取逻辑,并将其作为参数传递给遍历函数,确保后续处理能访问到目标位置。
  2. 传递目标文件夹参数:调整迭代处理函数,将目标文件夹参数传递到文件处理环节。
  3. 实现文件复制逻辑:替换原processFile的日志输出,编写文件复制代码,提供两种复制方案供选择。

完整改造后代码

function main() {
    // 替换为你的源根文件夹ID
    var sourceRootFolder = DriveApp.getFolderById('替换为源文件夹ID');
    // 替换为你的目标文件夹ID
    var targetRootFolder = DriveApp.getFolderById('替换为目标文件夹ID');
    processRootFolder(sourceRootFolder, targetRootFolder);
}

function processRootFolder(rootFolder, targetFolder) {
    MAX_RUNNING_TIME_MS = 1 * 60 * 1000;
    var RECURSIVE_ITERATOR_KEY = "RECURSIVE_ITERATOR_KEY";

    var startTime = (new Date()).getTime();

    // [{folderName: String, fileIteratorContinuationToken: String?, folderIteratorContinuationToken: String}]
    var recursiveIterator = JSON.parse(PropertiesService.getDocumentProperties().getProperty(RECURSIVE_ITERATOR_KEY));
    if (recursiveIterator !== null) {
        // 验证是否为同一文件夹
        if (rootFolder.getName() !== recursiveIterator[0].folderName) {
            console.warn("检测到新文件夹,清除旧迭代器。");
            recursiveIterator = null;
        } else {
            console.info("恢复之前的续跑会话。");
        }
    }
    if (recursiveIterator === null) {
        console.info("启动新遍历会话。");
        recursiveIterator = [];
        recursiveIterator.push(makeIterationFromFolder(rootFolder));
    }

    while (recursiveIterator.length > 0) {
        recursiveIterator = nextIteration(recursiveIterator, targetFolder);

        var currTime = (new Date()).getTime();
        var elapsedTimeInMS = currTime - startTime;
        var timeLimitExceeded = elapsedTimeInMS >= MAX_RUNNING_TIME_MS;
        if (timeLimitExceeded) {
            PropertiesService.getDocumentProperties().setProperty(RECURSIVE_ITERATOR_KEY, JSON.stringify(recursiveIterator));
            console.info("已运行%d毫秒,达到时间限制,暂停执行,请再次运行脚本继续。", elapsedTimeInMS);
            return;
        }
    }

    console.info("遍历及复制完成");
    PropertiesService.getDocumentProperties().deleteProperty(RECURSIVE_ITERATOR_KEY);
}

// 处理下一个文件或文件夹
function nextIteration(recursiveIterator, targetFolder) {
    var currentIteration = recursiveIterator[recursiveIterator.length - 1];
    if (currentIteration.fileIteratorContinuationToken !== null) {
        var fileIterator = DriveApp.continueFileIterator(currentIteration.fileIteratorContinuationToken);
        if (fileIterator.hasNext()) {
            // 处理下一个文件
            var path = recursiveIterator.map(function(iteration) { return iteration.folderName; }).join("/");
            processFile(fileIterator.next(), path, targetFolder);
            currentIteration.fileIteratorContinuationToken = fileIterator.getContinuationToken();
            recursiveIterator[recursiveIterator.length - 1] = currentIteration;
            return recursiveIterator;
        } else {
            // 文件处理完成
            currentIteration.fileIteratorContinuationToken = null;
            recursiveIterator[recursiveIterator.length - 1] = currentIteration;
            return recursiveIterator;
        }
    }

    if (currentIteration.folderIteratorContinuationToken !== null) {
        var folderIterator = DriveApp.continueFolderIterator(currentIteration.folderIteratorContinuationToken);
        if (folderIterator.hasNext()) {
            // 处理下一个子文件夹
            var folder = folderIterator.next();
            recursiveIterator[recursiveIterator.length - 1].folderIteratorContinuationToken = folderIterator.getContinuationToken();
            recursiveIterator.push(makeIterationFromFolder(folder));
            return recursiveIterator;
        } else {
            // 子文件夹处理完成
            recursiveIterator.pop();
            return recursiveIterator;
        }
    }

    throw "程序逻辑错误,不应执行到此处";
}

function makeIterationFromFolder(folder) {
    return {
        folderName: folder.getName(),
        fileIteratorContinuationToken: folder.getFiles().getContinuationToken(),
        folderIteratorContinuationToken: folder.getFolders().getContinuationToken()
    };
}

// 方案A:直接复制所有文件到目标文件夹根目录
// function processFile(file, path, targetFolder) {
//     console.log("复制文件:" + path + "/" + file.getName());
//     // 复制文件到目标文件夹,自动处理同名文件(添加"副本"后缀)
//     file.makeCopy(file.getName(), targetFolder);
// }

// 方案B:保持原目录结构,在目标文件夹创建对应子文件夹后复制
function processFile(file, path, targetFolder) {
    console.log("复制文件:" + path + "/" + file.getName());
    // 根据原路径在目标文件夹创建对应子文件夹
    var currentTargetFolder = targetFolder;
    var pathSegments = path.split("/");
    // 遍历路径片段,逐层创建文件夹(如果不存在)
    for (var i = 0; i < pathSegments.length; i++) {
        var folderName = pathSegments[i];
        var existingFolder = currentTargetFolder.getFoldersByName(folderName).next();
        if (!existingFolder) {
            existingFolder = currentTargetFolder.createFolder(folderName);
        }
        currentTargetFolder = existingFolder;
    }
    // 复制文件到对应子文件夹
    file.makeCopy(file.getName(), currentTargetFolder);
}

注意事项

  • 请替换代码中的替换为源文件夹ID和替换为目标文件夹ID为实际的文件夹ID
  • 第一次运行脚本时,需要授权脚本访问Google Drive的权限
  • 若目标文件夹存在同名文件,makeCopy方法会自动添加"副本"后缀;如需覆盖或其他处理逻辑,可添加额外判断
  • 原代码的超时续跑逻辑完全保留,当脚本达到运行时间限制暂停后,再次运行即可继续未完成的复制任务

内容的提问来源于stack exchange,提问作者OmarPoch

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 02:27:42