問題点
Google Apps Script(GAS)を使ってGoogle Drive上のファイルを指定したフォルダへコピーする場合、多くの場合はmakeCopy(destination)を使うかと思われます。destinationはコピー先のフォルダです。いろいろなファイルをコピーしていると、スタンドアロンプロジェクトだけがルートフォルダ(マイドライブ)へ作成されることが認められます。バグなのかもしれませんが、他でもお困りの方々がおられましたので、こちらでもこの問題を回避する方法について紹介させていただきます。
回避方法
ここではDrive APIを使用します。ただし、Drive APIのcopyメソッド(v2, v3共に)もスタンドアロンプロジェクトだけは指定したフォルダではなく、ルートフォルダへコピーされてしまいます。そこで、Drive APIのupdateを用いることでこの問題を回避することにしました。具体的な流れは次の通りです。
- makeCopy()あるいはDrive APIのcopyを使ってファイルをコピーする。
- スタンドアロンプロジェクトのファイルだけ、コピー後にDrive APIのupdateを使ってparent IDを変更してフォルダを移動させます。
これによりスタンドアロンプロジェクトも指定したフォルダへコピーすることができます。
サンプルスクリプト
サンプルとして、あるフォルダ(srcFolderId)内のファイルを指定したフォルダ(dstFolderId)へコピーするためのサンプルスクリプトを用意しました。環境に合わせてカスタマイズしてください。
function makeCopy(srcFolderId, dstFolderId) {
var srcFolder = DriveApp.getFolderById(srcFolderId);
var dstFolder = DriveApp.getFolderById(dstFolderId);
var files = srcFolder.getFiles();
while (files.hasNext()) {
var file = files.next();
var f = file.makeCopy(dstFolder);
if (file.getMimeType() == MimeType.GOOGLE_APPS_SCRIPT) {
Drive.Files.update({"parents": [{"id": dstFolderId}]}, f.getId());
}
}
}
function run() {
var srcFolderId = "### folder ID with source files ###";
var dstFolderId = "### destination folder ID ###";
makeCopy(srcFolderId, dstFolderId);
}
スクリプトの使い方
- このスクリプトを使用する際は、Drive APIをGoogleの拡張サービス(スクリプトエディタ上で、リソース -> Googleの拡張サービス -> Drive API)でDrive APIを有効にしてください。
- srcFolderId, dstFolderIdはそれぞれフォルダIDです。フォルダIDをセットして
run()
を実行すると、srcFolderIdのフォルダ内にあるファイルがdstFolderIdのフォルダへコピーされます。このとき、スタンドアロンプロジェクトのファイルもコピーできていることが分かります。
付録
- フォルダの移動はDrive API v3でも可能なのですが、Drive API v2のupdateメソッドではparentIdを直接変更できるのに対して、v3のそれではparentIdを直接変更することはできないようになっており、addParentsとremoveParentsのパラメータを使用する必要があります。
- 例えば、テストとして
if (file.getMimeType() == MimeType.GOOGLE_APPS_SCRIPT) {Drive.Files.update({"parents": [{"id": dstFolderId}]}, f.getId());}
を削除して実行すると、スタンドアロンプロジェクトのファイルだけがルートフォルダへコピーされていることが分かるかと思います。 - Drive APIを使用しない場合は、下記のようにスクリプトを変更してください。
From:
Drive.Files.update({"parents": [{"id": dstFolderId}]}, f.getId());
To:
dstFolder.addFile(file);
f.getParents().next().removeFile(file);
- 少し速度を向上させるためにバッチリクエストを使用したサンプルはこちらでご覧いただけます。