3
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

[GAS] Goole Apps Script を使って GoogleDrive のファイルを別アカウントの GoogleDrive に一括コピーする

Posted at

個人の 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);
  }
}
3
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?