Googleドライブで、フォルダー直下のファイルを別フォルダーへコピーする方法を説明します。
以下のGASは直下のファイルだけが対象です。
サブフォルダー、その中のファイル、階層全体は複製しません。
元ファイルを別の場所へ移動する処理とも異なります。
ファイルコピー・階層の複製・ショートカットを分ける
| 目的 | 選ぶ操作 |
|---|---|
| 直下のファイルだけをコピー | 新しいファイルIDの複製を作る。本稿のGASの対象 |
| 階層全体を複製 | 子フォルダーの作成と再帰的な処理が別途必要。本稿のコードの対象外 |
| 同じ元ファイルを別の場所から開く | ショートカットを使う。独立した複製ではない |
| 元ファイルの保存先を変える | 移動。コピー元から元ファイルがなくなる操作 |
少数ファイルを手作業で複製する場合
コピー元で複製したいファイルだけを選び、右クリックなどのメニューから「コピーを作成」を使います。
子フォルダーまで一緒に選ばないでください。
新しいコピーを元ファイルと見分けてから、コピーだけを移動操作でコピー先へ移します。
移動先とファイル数を確認し、元ファイルが元の場所に残っているかも確かめます。
フォルダー選択時にも同じコピー操作が使えると判断しないでください。
練習フォルダーと期待する結果
コピー元へsample_sample.txtとnotes.txtを置き、子フォルダーの中にchild.txtを置きます。
別に空の「コピー先」を作ります。
直下コピーの結果は2ファイルで、child.txtと子フォルダーはコピー先に入りません。
練習用データは練習用ファイル・コード・ローカル検証をまとめたZIPから取得できます。

撮影前に専用の2ファイルをDrive APIでコピーし、新しいIDと保存先、元と同じ読み取り本文、所有者だけの権限を確認しました。
元の子フォルダーにはchild.txtが残っています。
これはDrive APIでの実機確認で、以下のGASを実行した結果ではありません。
直下50ファイル以内をコピーするGAS
新規Apps Scriptプロジェクトへ貼り付け、COPY_SOURCE_IDとCOPY_DESTINATION_IDを自分の専用練習フォルダーのIDへ変更します。
コピー先にファイルまたは子フォルダーがある場合は、再実行による重複を避けるため停止します。
ショートカットやApps Scriptプロジェクトなど、この例で扱わないGoogle形式も事前に停止します。
const COPY_SOURCE_ID = 'コピー元の練習用フォルダーID';
const COPY_DESTINATION_ID = '空のコピー先フォルダーID';
function directCopyPlan_() {
if (COPY_SOURCE_ID === COPY_DESTINATION_ID) {
throw new Error('コピー元とコピー先は別フォルダーにしてください');
}
const source = DriveApp.getFolderById(COPY_SOURCE_ID);
const destination = DriveApp.getFolderById(COPY_DESTINATION_ID);
if (destination.getFiles().hasNext() || destination.getFolders().hasNext()) {
throw new Error('コピー先が空ではありません。再実行せず結果を確認してください');
}
const iterator = source.getFiles(); // 子フォルダーには入らない
const files = [];
while (iterator.hasNext()) {
if (files.length >= 50) throw new Error('練習対象は50ファイル以内です');
const file = iterator.next();
const mime = file.getMimeType();
const nativeAllowed = [MimeType.GOOGLE_DOCS, MimeType.GOOGLE_SHEETS,
MimeType.GOOGLE_SLIDES, MimeType.GOOGLE_DRAWINGS];
if (mime.startsWith('application/vnd.google-apps.') && !nativeAllowed.includes(mime)) {
throw new Error('この練習では扱わない種類です: ' + file.getName());
}
files.push(file);
}
return { destination, files };
}
function previewDirectCopy() {
const plan = directCopyPlan_();
console.log(JSON.stringify(plan.files.map(file => ({ id: file.getId(), name: file.getName() })), null, 2));
}
function copyDirectFiles() {
const plan = directCopyPlan_(); // 全件確認を終えてから複製する
const results = [];
try {
for (const file of plan.files) {
const copy = file.makeCopy(file.getName(), plan.destination);
results.push({ sourceId: file.getId(), copyId: copy.getId(), name: copy.getName() });
console.log(JSON.stringify(results[results.length - 1]));
}
} catch (error) {
console.log(JSON.stringify({ completed: results, error: String(error) }));
throw error; // 途中成功したコピーは残る。コピー先を確認してから復旧する
}
console.log('コピーしたファイル数: ' + results.length);
return results;
}
プレビュー・実行・照合の順番
previewDirectCopyを実行し、対象ID・名前・件数を確認します。
元と先が同じではないこと、コピー先が空で非公開であることも確かめます。
作業中に他の人が元フォルダーを変更しない状態で、copyDirectFilesを実行します。
実行時にも対象を読み直すので、プレビュー後の変更があれば先に確認し直してください。
ログにはsourceIdとcopyIdが出ます。
新しいIDのファイルがコピー先にあり、元ファイルはコピー元に残ることを確認します。
makeCopy(name, destination)で保存先を指定できるため、コピー後にDrive APIのparentsを書き換える処理は不要です。
旧実装のDrive.Files.updateとApps Script用の特別分岐は使いません。
仕様はFile.makeCopyの公式説明とFolder.getFilesの公式説明を参照できます。
失敗後に再実行せず、残ったコピーを確認する
途中で権限や利用制限のエラーが起きると、成功済みのコピーは残ります。
ログのcompletedを保存し、コピー先の件数とIDを照合します。
コピー先が空ではないため、そのままの再実行は停止します。
必要なら別の空の練習用コピー先で、対象を見直してから実行します。
元を削除して帳尻を合わせる方法は使いません。
元へ戻したい場合は、元ファイルが変わっていないことを確認して元を使用します。
コピーの整理はcopyIdで対象を特定し、元ファイルと取り違えないように行ってください。
この検証では完全削除やゴミ箱を空にする操作は行っていません。
コピーで維持されるものを決めつけない
アクセス権、コメント、版履歴、Apps Scriptのトリガーや外部認証が元と同じになるとは判断しないでください。
共有先や保存先の権限はGoogleドライブ│共有設定と権限の違い|閲覧者・コメント可・編集者・リンク共有で確認します。
コピーを自分が所有すると、自分の保存容量を使用するのでGoogleドライブの容量が減らないときに見る順番|消しても空かない理由も確認してください。
掲載GASは構文とローカル模擬の確認までで、GASのDrive権限取得・実行は未検証です。
関連する既存記事と案内
関連する既存記事と商品案内を以下に掲載しています。
練習は本文の対象範囲を確認して進め、未検証の実行を確認済みとして扱わないでください。






