GoogleAppsScript

Google Driveでディレクトリごとまるっとコピーしてやるぜ!

More than 3 years have passed since last update.

きっかけ

Advent Calendarで何を書こうか迷っていた時に、こんなツイートを見たわけです。

https://twitter.com/sinmetal/status/544314381379452929

Google Driveには、ディレクトリのコピーがメニューにない

Google Driveでディレクトリで右クリックしてみました。

マイドライブ_-_Google_ドライブ.png

ファイルを右クリックすると「コピーを作成」がある。
chugoku-gtug_-_Google_ドライブ.png

Google Apps Scriptで実現するしかなさそう

ということで、作ってみました。

コード.gs
function myFunction() {
  var folders = DriveApp.getFoldersByName("コピーサンプルデータ");
  var dest = DriveApp.createFolder("コピーサンプルデータのコピー");
  while(folders.hasNext()) {
    var folder = folders.next();
    folderCopy(folder, dest);
  }
}

function folderCopy(folder, dest) {
  // var folders = DriveApp.getFolders();
  var folders = folder.getFolders();
  var files = folder.getFiles();

  while(files.hasNext()) {
    var file = files.next();
    // file.makeCopy(dest);とすると、****のコピーというファイル名になるので…。
    file.makeCopy(file.getName(), dest);
  }

  while(folders.hasNext()) {
    var subFolder = folders.next();
    var folderName = subFolder.getName();
    var copyFolder = dest.createFolder(folderName);
    folderCopy(subFolder, copyFolder);
  }  
}


承認が必要なので

Driveへのアクセスの承認をして下さい。

許可のリクエスト.png

解説

DriveAppにはフォルダのコピーAPIがない。

DriveAppにはフォルダのコピーを作るというAPIがないので、同じ名前でフォルダを作ってやらないといけません。
ということで、フォルダを階層を維持したまま別の所にコピーするのを実現するには、フォルダを探索する再帰呼び出しをしてやります。

DriveApp.getFolders()/Folder.getFolders()はフォルダしか取得できない。

当然ですが、getFolders()を呼び出してもファイルは取得されないので、フォルダの探索と同時にファイルの探索File.getFiles()を呼び出して、ファイルのコピーを作っています。

File.makeCopy(dest)にすると、****のコピーというファイル名になるので…。

FileにはmakeCopy()というAPIがありますが、名前を指定しないものを呼び出すと"****のコピー"というファイル名になってしまいます。(その方が都合が良い場合もありますが)コピーを作る時は、同じファイル名で作ると思いますから、File.makeCopy(name, dest)の方を呼び出してファイル名が変わらないように制御します。

ただし、弱点が

コピーを作る先がルートフォルダになる。これは、destの指定がまずいだけですが、DriveApp.createFolder()を使うと、ルートディレクトリにFolderを作ってしまうので、パスを指定してFolderを作る方法があればもう少し便利になるかもしれない。

結論

今年は「早すぎる男」になれませんでした…。

Disclaimer

  • この記事は個人的なものです。私の雇用者とは全く関係はありません。(一応つけておきます)