個人の GoogleDrive に入れていたファイルを GoogleWorkspace の共有ドライブに移行したのですが、複数の所有者がいたため単純なドラッグ・ドロップで移動ができませんでした。
所有者問題はファイルのコピーを作成することで回避できるのですが、ひとつずつやるのは骨が折れるので GAS を使って一括コピーしました。
やり方
GooleDrive にアクセスして、新規 > その他 > Google Apps Script
を選び、プロジェクトを作成します。
下記のスクリプトを記述し、コピー元フォルダ ID
、コピー元フォルダ ID
を環境に合わせて書き換えます。
保存をしたら 実行
すれば処理を開始します。
注意点
- 必ずテスト用フォルダを作って一度テストしてください。
- あまりにも大量にファイルがあると落ちるかもしれません。
- 筆者は4階層200ファイルくらいでしかテストしてません。
- フォルダ毎に実行したほうが安全だと思います。
- うっかりファイルが消えても補償できません。自己責任でお願いします。
- 不具合があったら教えてください。
スクリプト
コピー元フォルダ ID
、コピー元フォルダ ID
を環境に合わせて書き換えます。
フォルダIDはURLの最後の部分です。
https://drive.google.com/drive/folders/1234567890ABCDEFGabcdefg
だったら
1234567890ABCDEFGabcdefg
です。
copyMode
に同名ファイルが存在した時の動作を指定してください。
MODE_OVERRIDE
を選択しても別のアカウントがオーナーのファイルは削除できないので、そのファイルについては MODE_ADD_NUMBER
が実行されます。
/**
* GoogleDriveのファイルを下層もまとめてコピーする
* 同じファイルがあった場合は「上書き / 無視 / 日付が新しいほうを残す」を選べる
* GoogleDriveは仕様上同名のファイルが存在できるが、このスクリプトでは1つしか許可しない前提
*/
// コピー元フォルダ ID
const src = 'xxxxxxxxxxxxxxxxxxxxxxx';
// コピー先フォルダ ID
const dist = 'xxxxxxxxxxxxxxxxxxxxxxx';
// 同じファイルがあった時の動作
const MODE_OVERRIDE = 1; // 上書き。権限がなければ MODE_ADD_NUMBER になる
const MODE_CANCEL = 2; // 無視
const MODE_NEWDAY = 3; // 新しければコピーする
const MODE_ADD_NUMBER = 4; // 数字を付ける
const copyMode = MODE_OVERRIDE;
/**
* 開始
*/
function myFunction() {
copyFolder(src, dist, '');
}
/**
* フォルダをコピー
*/
function copyFolder(srcFolderId, distFolderId, pathStr){
const srcFolderObj = DriveApp.getFolderById(srcFolderId);
const distFolderObj = DriveApp.getFolderById(distFolderId);
const newPathStr = pathStr + '/' + srcFolderObj.getName();
console.log(newPathStr);
// フォルダ一覧取得して作成
const folderss = srcFolderObj.getFolders();
for (let i = 0; folderss.hasNext(); i++) {
const folder = folderss.next();
const folderName = folder.getName();
let newFolder;
// フォルダが存在しなければ作成する
const folderIterator = distFolderObj.getFoldersByName(folderName);
if (folderIterator.hasNext()) {
newFolder = folderIterator.next();
} else {
newFolder = distFolderObj.createFolder(folderName);
}
// さらに下層に入る
copyFolder(folder.getId(), newFolder.getId(), newPathStr);
}
// ファイルコピー
copyFiles(srcFolderObj, distFolderObj);
}
/**
* ファイルをコピー
*/
function copyFiles(srcFolderObj, distFolderObj){
const files = srcFolderObj.getFiles();
for (let i = 0; files.hasNext(); i++) {
const file = files.next();
const fileName = file.getName();
const existsFiles = distFolderObj.getFilesByName(fileName);
// 既存ファイルが存在したらモードによって動作を変える
if (existsFiles.hasNext()){
switch(copyMode) {
case MODE_OVERRIDE:
// 同名があったら上書きする
copyOverride(distFolderObj, file, fileName, existsFiles.next());
break;
case MODE_ADD_NUMBER:
// 同名があったら番号を付ける
copyAddNumber(distFolderObj, file, fileName);
break;
case MODE_NEWDAY:
// 新しければコピーする
copyNewDay(distFolderObj, file, fileName, existsFiles.next());
break;
case MODE_CANCEL:
// 同名があったらコピーしない
break;
default:
}
} else {
// 同名ファイルが存在しないのでコピーする
file.makeCopy(fileName, distFolderObj);
}
}
}
/**
* 既存ファイルを削除してコピー
*/
function copyOverride(distFolderObj, srcFile, srcFileName, existsFile) {
// 同名ファイルを削除してからコピー
// 削除失敗したら番号追加でコピー
try {
existsFile.setTrashed(true);
srcFile.makeCopy(srcFileName, distFolderObj);
} catch(e) {
copyAddNumber(distFolderObj, srcFile, srcFileName);
}
}
/**
* 番号を付けてコピー
*/
function copyAddNumber(distFolderObj, srcFile, srcFileName) {
let count = 1;
let newFileName, existsFiles;
// 既存ファイルが存在しなくなるまで番号を追加
do {
newFileName = srcFileName + '_' + count;
existsFiles = distFolderObj.getFilesByName(newFileName);
count += 1;
} while (existsFiles.hasNext());
srcFile.makeCopy(newFileName, distFolderObj);
}
/**
* 新しければコピーする
*/
function copyNewDay(distFolderObj, srcFile, srcFileName, existsFile) {
const srcUpdate = srcFile.getLastUpdated();
const existsUpdate = existsFile.getLastUpdated();
if (srcUpdate > existsUpdate) {
copyOverride(distFolderObj, srcFile, srcFileName, existsFile);
}
}