如何使用 Google Apps 脚本在个人 Google 云端硬盘和团队云端硬盘之间移动文件?

Posted

技术标签:

【中文标题】如何使用 Google Apps 脚本在个人 Google 云端硬盘和团队云端硬盘之间移动文件?【英文标题】:How can I use Google Apps Script to move files between personal Google Drives and Team Drives? 【发布时间】:2017-09-21 13:45:04 【问题描述】:

最近,我通过 Google 的 Team Drive early adopter 计划访问了 Google Team Drive。

我将created a Google Docs file 称为Hello, world!,然后编写了一个简短的Google Apps 脚本函数,该函数使用addFile() 方法更新文件附加到哪个Google Drive 文件夹:

function move_or_link_file() 
  var source = DriveApp.getFolderById("<sourceID>");
  var fileiter = source.getFilesByName("Hello, world!");
  var dest = DriveApp.getFolderById("<destID>");
  while (fileiter.hasNext()) 
    var file = fileiter.next();
    dest.addFile(file);
  

通常,Google 云端硬盘文件夹的 URL 与以下模式匹配:https://drive.google.com/drive/folders/&lt;alphanumericID&gt;。虽然可能有点不优雅,但我可以在各种操作场景和条件下测试我的代码,只需在网络浏览器中打开不同的 Google Drive 文件夹组合,选择文件夹 URL 的 &lt;alphanumericID&gt; 部分,然后手动复制并 -将此字符串的值粘贴到 &lt;sourceID&gt;&lt;destID&gt;

经过测试,我能够识别出四种不同的输入条件,这些条件会导致三种不同的行为:

案例 1:&lt;sourceID&gt;&lt;destID&gt; 都是我个人 Google Drive 中的文件夹:

在这种情况下,脚本的行为就好像它正在创建一个符号链接:Hello, world! 文件现在出现在两个目录中。请注意,它确实是同一个文件,不是两个相同的副本:例如,如果我打开文档,那么文档 URL 与文件夹 URL 一样,也遵循以下模式:https://docs.google.com/document/d/&lt;documentID&gt;/edit。我可以看出文件是相同的,因为当我打开它时,文档的 URL 共享相同的 &lt;documentID&gt;,无论我使用哪个父文件夹来访问它。

对于案例 1,我还可以通过简单地将附加行 source.removeFile(file); 附加到文件迭代器循环的末尾来使脚本的行为更像 mv 命令。

案例 2:&lt;sourceID&gt; 是我个人 Google 云端硬盘中的一个文件夹,而 &lt;destID&gt; 是团队云端硬盘中的一个文件夹:

在这种情况下,脚本的行为默认类似于 mv 命令,而不是符号链接,即使没有额外调用我在案例 1 中提到的 removeFile() 方法:即 Hello, world!文件从我的个人驱动器中消失,然后重新出现在团队驱动器中。

案例 3:&lt;sourceID&gt;&lt;destID&gt; 都是 Google 团队云端硬盘中的文件夹:

这会导致来自 Google Apps 脚本的错误消息:Cannot use this operation on a Team Drive item. (line 7, file "move_or_link_file")

案例 4:&lt;sourceID&gt; 是团队云端硬盘中的一个文件夹,而&lt;destID&gt; 是我个人 Google 云端硬盘中的一个文件夹:

与案例 3 相同的错误。

现在这是真正奇怪的部分:GSuite 图形用户界面(即当您通过网络浏览器访问 Google Drive 文件和文件夹时使用的界面)通过弹出窗口提供Move 命令右键单击文件。这个 GUI 版本的类 Unix mv 命令在上述所有四种情况下的行为都是相同的:无论您是在个人驱动器或团队驱动器之间来回移动文件夹,还是在驱动器内部来回移动文件夹,它每次都能正常工作并将文件移动到您期望的位置。

所以,我认为通过 Google 的 API 实现 mv 命令一定是可能的,因为他们显然已经为 GUI 界面的用户做到了。

因此我的问题是:鉴于 经验上可能在个人驱动器和团队驱动器中的任意文件夹组合之间来回移动文件,我将如何实际做到这一点,仅使用提供的 API 调用通过 Google Apps 脚本?

另外,还有一个额外的问题:假设与案例 1 类似,我不是在同一个团队云端硬盘中的两个不同文件夹之间移动文件,而是实际上想创建一个符号链接,将文件附加到两个文件夹 - 如何我也使用 Google API 来做到这一点? (即,我怎样才能让案例 3 的行为更像案例 1?)

【问题讨论】:

在你使用GUI实现3&4的地方,检查生成的文件是否具有相同的ID。我怀疑它可能正在复制并创建一个新文件。尽量不要将文件夹视为文件夹。查看***.com/questions/41741520/…的答案 @pinoyyid:好的,我仔细检查了GUI“移动到”命令,这绝对是一个真正的“移动”操作——文件在移动前后具有相同的ID;这不是副本。这强化了我之前所说的:Google 以某种方式在 GUI 中实现了“移动”操作,无论选择父文件夹(或者,无论选择 Collection 标签,都遵循您在链接中引用的命名法),该操作都有效,但是目前尚不清楚如何在 Google Apps 脚本中重现该行为。 【参考方案1】:

Google 团队云端硬盘最近才开始允许使用一般脚本。我可以想象在情况 2 甚至不是预期的情况下您能够实现的文件移动。团队驱动仍有一些限制(例如,您不能移动文件夹)。

对于案例 1,我可以简单地指出您的脚本实际上不是移动命令。您实际上应该将 Google Drive 文件夹想象为 Gmail 标签。文件可以根本没有文件夹。您的脚本只是为文件分配一个标签,因此它可以出现在许多文件夹中(就像一封电子邮件可以有许多 Gmail 标签并出现在每个标签“文件夹”中)。

它适用于情况 2,因为团队云端硬盘是与您的个人云端硬盘分开的实体。本质上,当您将其添加到团队驱动器时,您必须放弃文件的所有权。据我所见,团队驱动器认为向其中添加文件意味着应该从所有其他父级中删除它。我认为这就是为什么在案例 3 和 4 中您不能移动任何项目的原因。所有者是团队驱动器本身,但命令是作为普通 Gsuite 用户发送的。

Drive REST api 最近(~3 月初)更新为与团队驱动器一起使用:https://developers.google.com/drive/v3/web/about-teamdrives 所以我相信从技术上讲您正在寻找的东西可以完成,但是考虑到团队驱动器仍然存在一些限制,我不要认为它会被记录在案。

【讨论】:

以上是关于如何使用 Google Apps 脚本在个人 Google 云端硬盘和团队云端硬盘之间移动文件?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Google Apps 脚本中使用服务帐户对 Google 表格进行身份验证

如何使用 Google Apps 脚本将公式添加到 Google 表格?

使用 Google Apps 脚本在 Google 表格中创建新表格

如何使用 Google Apps 脚本执行 API + Java 创建 Google 表单?

如何使用 Google Apps 脚本在电子表格中查找按钮的位置?

如何通过 Apps 脚本在 Google 表格中“清除格式”