Google Driveを使用しているとファイルを別のフォルダへ移動させたくなる場合があります。本記事では、このファイル移動についてGoogle Apps Script (GAS)を使った2つの方法をご紹介します。丁度、ファイルの別フォルダへの移動についてAdvanced Drive Serviceでも可能であると教わりましたので勉強を兼ねて調べましたので、覚書としてまとめました。
DriveAppを使用した場合
20200903更新
2020年7月27日にaddFile(File)
, addFolder(Folder)
, removeFile(File)
, removeFolder(Folder)
のメソッドが廃止され、これと同時に、下記の新たなメソッドが追加されました。
これにより、ファイル、あるいはフォルダーの移動は下記のように行うことができるようになりました。
ファイルの移動
const fileId = "###"; // 移動させるファイルのファイルID
const folderId = "###"; // 移動先のフォルダID
const file = DriveApp.getFileById(fileId);
const folder = DriveApp.getFolderById(folderId);
file.moveTo(folder);
フォルダの移動
const srcFolderId = "###"; // 移動させるフォルダのフォルダID
const dstFolderId = "###"; // 移動先のフォルダID
const srcFolder = DriveApp.getFolderById(srcFolderId);
const dstFolder = DriveApp.getFolderById(dstFolderId);
srcFolder.moveTo(dstFolder);
@unauさんのご指摘を反映させていただきました。
下記スクリプトはStandalone scriptあるいはContainer bound scriptで使用します。
この方法ではコピー元ファイルのフォルダ情報にコピー先のフォルダ情報を追加し、その後コピー元のフォルダ情報を削除する流れです。新たなフォルダ情報を追加する前に元のフォルダ情報を削除しても問題ありません。
var sourcefile = [コピー元ファイル名]; // file name
var destfolder = [コピー先フォルダ名]; // folder name
var destfolder = DriveApp.getFoldersByName(destfolder).next();
var file = DriveApp.getFilesByName(sourcefile).next();
var sourcefolder = file.getParents().next();
destfolder.addFile(file);
sourcefolder.removeFile(file);
Google Drive APIsを使用した場合
この方法では直接ファイルの情報を更新してフォルダ位置を変更する流れです。詳細はこちらをご覧ください。この方法では事前の準備が必要です。
事前準備
-
スクリプトのプロジェクトを開いて、上部の 「リソース」 - 「Googleの拡張サービス」 - 「Drive API」をONにする。
-
Google Developers Consoleのライブラリにて 「Google Drive API」 を検索して有効にする。
-
Google Developers Consoleでプロジェクト作成とClient ID, Client secretを取得し、codeを取得する。
-
アクセストークンを取得 : こちらの記事が分かりやすいと思います。
GASのサンプルスクリプト
これを実行するには事前準備で取得したアクセストークンが必要です。実際に実行したとき、このような方法でもファイル移動ができるのかと感心させられました。
var sourcefile = DriveApp.getFilesByName([コピー元ファイル名]).next().getId(); // file name
var destfolder = DriveApp.getFoldersByName([コピー先フォルダ名]).next().getId(); // folder name
var accesstoken = [アクセストークン];
UrlFetchApp.fetch('https://www.googleapis.com/drive/v2/files/' + sourcefile, {
method:'put',
headers: {
'Authorization': 'Bearer ' + accesstoken,
'uploadType' : 'multipart/related'
},
contentType: 'application/json',
payload: JSON.stringify({'parents': [{id: destfolder}]})
});
UrlFetchApp.fetchを使用せずに拡張サービスを利用して直接Drive APIを使用すると、アクセストークンの入力は不要になり、下記のようにシンプルになります。
Drive.Files.update(
{"parents": [{"id": "## Folder ID ##"}]},
"## File ID ##"
)
ローカルからの使用
Google Drive APIsを使用する場合、DriveAppを使用する場合よりも事前準備は大変ですが、この方法ではGoogle Drive上だけでなく、ローカルからでもcurlなどでGASのサンプルスクリプトと同じ動作をさせることができます。
$ curl -X PUT -H 'Content-Type: application/json' -H 'uploadType: multipart/related' -H 'Authorization: Bearer [アクセストークン]' https://www.googleapis.com/drive/v2/files/[コピー元ファイルID] -d '{"parents": [{"id": "[コピー先フォルダID]"}]}'
上記の実行時には移動先のフォルダIDと移動させたいファイルIDを直接指定する必要がありますので次のようなコマンドでファイル名、ファイルIDを取得して対応させてください。この詳細はこちらでご覧いただけます。リファレンスを見ていると、かなりのことができるようで楽しめそうです。
$ curl -H 'Content-Type: application/json' -H 'Authorization: Bearer [アクセストークン]' https://www.googleapis.com/drive/v2/files -o list.json
URLへ"orderBy=folder"を付け加えるとfolderが先に表示されます。データはJSONで出力されますのでjqを使用してファイル名、ファイルIDをそれぞれ下記のように取得することができます。
$ jq -r ".items[].title" list.json
ファイル名
$ jq -r ".items[].id" list.json
ファイルID
はまったところ
初めはScriptApp.getOAuthToken()でアクセストークンを取得しようとして下記のようなエラーで困っていました。説明を見ると、全てに対応していないとあったため、こちらの記事を参考にさせていただき、手動でアクセストークンを取得することで無事解決することができました。
{
"error": {
"errors": [
{
"domain": "global",
"reason": "insufficientPermissions",
"message": "Insufficient Permission"
}
],
"code": 403,
"message": "Insufficient Permission"
}
}
GASは奥が深いですね。