きっかけ
Advent Calendarで何を書こうか迷っていた時に、こんなツイートを見たわけです。
Google Driveには、ディレクトリのコピーがメニューにない
Google Driveでディレクトリで右クリックしてみました。
Google Apps Scriptで実現するしかなさそう
ということで、作ってみました。
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へのアクセスの承認をして下さい。
解説
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
- この記事は個人的なものです。私の雇用者とは全く関係はありません。(一応つけておきます)