Googleドライブのファイル管理、もう手作業で消耗しない!GAS自動化の衝撃

Googleドライブに教材や会議資料を保存していると、一つのフォルダにPDFがたまり、探しにくくなることがあります。保存先のルールが決まっているなら、Google Apps Script(GAS)を使って、ファイルを振り分ける処理を作れます。

この記事では、指定したフォルダの直下にあるPDFを、Googleドライブ上の作成年別に整理します。最初に移動予定をログで確認し、その後に移動を実行する構成です。まずは自分が所有するテスト用フォルダと、数件のPDFで試してください。

目次

今回作る整理処理の範囲

処理の対象は、指定フォルダの直下にあるPDFです。同じフォルダ内に「2025」「2026」などの年別フォルダを作り、該当するPDFを移動します。すでに対象年のフォルダが一つ存在する場合は、それを利用します。

分類に使うのは、getDateCreated() で取得するGoogleドライブ上の作成日時です。ファイル名に書かれた年度や、PDF本文の日付を読み取る処理ではありません。例えば、過年度の教材でも、ドライブ上の作成日時が今年なら今年のフォルダに分類されます。

項目このコードの動作
整理元指定した一つのフォルダ
対象整理元の直下にあるPDF
分類基準ドライブ上の作成日時を日本時間で判定した年
移動先整理元の中にある年別フォルダ
対象外PDF以外、ショートカット、サブフォルダ内のファイル
件数制限整理元直下のファイルが100件を超える場合は変更前に停止
事前確認ファイルを移動せず、予定をログに表示

100件という上限は、このサンプルで処理範囲を限定するために設けたものです。Googleドライブの保存件数上限ではありません。また、このコードにはファイルを削除する処理は含まれていません。

1.整理元フォルダとGASプロジェクトを準備する

まず、マイドライブにテスト用フォルダを作り、移動してもよいPDFを数件入れます。この記事の例は、自分が所有する通常のフォルダで試すことを前提にしています。共有ドライブや組織の共有資料への適用は、権限や運用条件を別途確認してください。

フォルダを開いたときのURLから、フォルダIDを取得します。例えば、https://drive.google.com/drive/folders/ABC123 なら、IDは ABC123 の部分です。続いてGoogle Apps Scriptで新しいプロジェクトを作り、次のコードを貼り付けます。

2.確認用と実行用の関数を用意する

コードの先頭にある SOURCE_FOLDER_ID を、整理元フォルダのIDに置き換えてください。previewPdfSort は移動予定の確認用、executePdfSort は実際の移動用です。まずは確認用の関数から実行します。

const SOURCE_FOLDER_ID = 'ここに整理元フォルダのID';
const TIME_ZONE = 'Asia/Tokyo';
const MAX_FILES = 100;

function previewPdfSort() {
  sortPdfByYear(true);
}

function executePdfSort() {
  sortPdfByYear(false);
}

function sortPdfByYear(dryRun = true) {
  const lock = LockService.getScriptLock();
  if (!lock.tryLock(1000)) {
    throw new Error('別の処理が実行中です。後で再実行してください。');
  }

  try {
    const source = DriveApp.getFolderById(SOURCE_FOLDER_ID);
    const files = source.getFiles();
    const plan = [];
    let checked = 0;

    while (files.hasNext()) {
      const file = files.next();
      checked++;
      if (checked > MAX_FILES) {
        throw new Error('整理元の直下に100件を超えるファイルがあります。対象を分けてください。');
      }
      if (file.getMimeType() !== MimeType.PDF) continue;
      const year = Utilities.formatDate(file.getDateCreated(), TIME_ZONE, 'yyyy');
      plan.push({ file, year });
    }

    // 移動前に、対象年のフォルダの重複を確認する。
    const destinations = new Map();
    for (const { year } of plan) {
      if (destinations.has(year)) continue;
      const matches = source.getFoldersByName(year);
      const folder = matches.hasNext() ? matches.next() : null;
      if (matches.hasNext()) {
        throw new Error(year + 'フォルダが複数あります。名前を整理してください。');
      }
      destinations.set(year, folder);
    }

    for (const { file, year } of plan) {
      console.log(JSON.stringify({
        mode: dryRun ? '確認のみ' : '移動開始',
        sourceId: source.getId(),
        fileName: file.getName(),
        fileId: file.getId(),
        destinationYear: year
      }));
      if (dryRun) continue;

      let folder = destinations.get(year);
      if (!folder) {
        folder = source.createFolder(year);
        destinations.set(year, folder);
      }
      file.moveTo(folder);
      console.log('移動成功: ' + file.getId());
    }

    console.log((dryRun ? '確認対象: ' : '移動完了: ') + plan.length + '件');
  } finally {
    lock.releaseLock();
  }
}

ファイルの移動には、DriveAppの moveTo() を使用しています。また、同じプロジェクトから処理が重なって実行されることを避けるため、スクリプトロックを利用しています。このロックは、人による操作や別のプロジェクトからの変更まで止めるものではありません。

3.移動予定を確認する

関数の選択欄で previewPdfSort を選び、実行します。初回はGoogleドライブへのアクセス許可を求められる場合があります。確認用の実行ではファイルを変更しませんが、同じプロジェクトに移動処理も含まれるため、承認画面ではコード全体に必要な権限が表示されることがあります。

実行ログには、ファイル名、ファイルID、移動先の年が表示されます。整理元が正しいか、意図したPDFだけが対象になっているか、作成年での分類が目的に合うかを確認してください。この段階では、年別フォルダも新規作成しません。

同じ名前の年別フォルダが複数ある場合は、どちらへ移動すべきか判断できないため停止します。該当フォルダの内容を確認し、名前を変更するなどして移動先を一つにしてから、再度確認用の関数を実行してください。

4.PDFを移動して結果を確認する

移動予定に問題がなければ、executePdfSort を選んで実行します。必要な年別フォルダが作成され、対象のPDFが移動します。確認後に整理元の内容が変わった場合、実行時の対象も変わるため、期間を空けた場合はもう一度プレビューしてください。

実行後はGoogleドライブを開き、ファイルが想定したフォルダに入っているか確認します。もう一度実行しても、移動済みのPDFは整理元の直下にないため、通常は処理対象になりません。新しく整理元へ追加したPDFは、次回の対象になります。

途中で権限不足などのエラーが発生した場合は、その時点で停止します。停止前に移動したファイルは、自動では元に戻りません。 実行ログの「移動成功」と実際の保存先を確認し、原因を解消してから再実行してください。

5.動作を確認してから定期実行を設定する

手動での確認が済んだら、GASの「トリガー」から時間主導型のトリガーを追加できます。実行する関数には executePdfSort を指定し、毎日や毎週など、ファイルが増える頻度に合わせて設定します。プレビュー用の関数を指定した場合は、定期的にログを出すだけになります。

インストール型トリガーは、作成したアカウントの権限で動作します。また、時間主導型の実行時刻には幅があるため、指定時刻ちょうどの実行を前提にしないでください。設定後も「実行数」の画面などで、失敗していないかを確認します。

自動整理を止めたい場合は、該当するトリガーを削除します。コードを残したままでも、定期実行の設定を外せば、そのトリガーによる処理は停止できます。

実行時間と件数の制限を確認する

Google公式資料では、通常のスクリプト実行時間の上限は1回6分です。トリガーの合計実行時間などにも別の制限があり、アカウント種別によって異なります。制限は変更される場合があるため、運用時には公式の割り当て一覧を確認してください。

このサンプルは、整理元直下のファイルが100件を超えると、フォルダ作成や移動を始める前に停止します。ただし、100件以内なら必ず制限時間内に完了するという保証ではありません。大量のファイルを扱う場合は、対象を分けるか、途中から再開できる仕組みが必要です。

Utilities.sleep() で待機時間を入れても、実行時間や1日の割り当てが増えるわけではありません。処理が遅い場合は、待機を追加する前に、対象件数やAPI呼び出し回数、実行ログを確認しましょう。

よくある質問

ファイル名にある年度で整理できますか?

可能ですが、今回のコードはドライブ上の作成日時を使っています。「2025年度_数学.pdf」のような名前から年度を取り出すには、命名ルールに合わせた別の処理が必要です。暦年と年度を混同しないよう、分類基準を先に決めてください。

サブフォルダ内のPDFも整理されますか?

今回のコードは、指定フォルダの直下だけを対象にしています。サブフォルダ内も調べるには、フォルダをたどる処理を追加する必要があります。対象範囲が広がるため、実行時間や移動先のルールも合わせて見直します。

古いファイルの自動削除にも使えますか?

今回のコードには削除処理を設けていません。作成日が古くても利用中の資料はあるため、削除を導入する際は、保存期限や利用状況に合わせた判定が必要です。なお、DriveAppのFileには setTrashed(true) はありますが、file.deleteFile() というメソッドはありません。

Learning Tools

記事を検索したい方はここから!

辞書から探す

本文中で気になった概念やキーワードを、辞書ページで一覧から確認できます。

辞書を見る