見出し画像

【GAS】 でGoogleドライブを操る! Folder/File Iteratorって何?の巻



Folder/File Iteratorとは何か

GASで複数のフォルダかファイルがまとまったものから一つひとつ取り出すことができる入れ物として利用されるものです。
フォルダなら”FolderIterator”クラス、ファイルなら”FileIterator”クラスです。

分かりずらく言ってしまったかもしれませんが、要は複数のフォルダかファイルから成るリストのようなものです。(厳密にはイテレータです)

※このページでは「複数」という意味を2つ以上ではなく、0以上のいくつでもという意味で使わせていただきます。ややこしいですが、お願いします。

何に使うのか?

複数のフォルダかファイルがまとまったものから、一つひとつ取り出して、その都度一つのフォルダかファイルを扱う為に使います。

ここで注意点として、ひとつのフォルダかファイルを扱うこと”しか”できません。
複数をまとめてどうこうできる機能はありません。あくまで一つずつなのです。

なぜ使うのか?

上記の説明から制約がありそうと感じたと思います。
単純に、複数のフォルダかファイルをリスト([fileA, fileB, fileC…])として取得して扱えば良いのではないかと思われたかもしれません。

できたらそうしたいのですが、GASの仕様上、複数のフォルダかファイルを扱うにはFolder/FileIteratorを使わざるを得ないからなのです。
なので、私の見解で「なぜ使うのか?」の問いの答えは、それしか方法がないからです。

複数のフォルダかファイルを扱う状況とは?

上記に何度も、複数のフォルダかファイルがまとまったものと出てきていますが、具体的にどういうことでしょう?

あるフォルダ内にある直属の全てのファイルを取得したいとき(folderObject.getFiles())や、特定の名前のフォルダを取得したいとき(DriveApp.getFolderByName(name))などです。

そしてそれらの関数の戻り値は、複数のフォルダがまとまったものならFolderIteratorクラス、複数のファイルがまとまったものならFileIteratorクラスのオブジェクトになります。

FolderIteratorとFileIteratorの違いは?

フォルダのみがまとまったものが、FolderIterator。
ファイルのみがまとまったものが、FileIterator。

注意点!

FolderIteratorまたはFileIteratorは、フォルダかファイルを一つずつ取り出すことしかできません。
フォルダかファイルがイテレータにいくつあるか(.length()などで確認できない)、または一覧で確認できないのです。

どのように使うのか?

FolderIteratorとFileIteratorは、中身がフォルダかファイルかの違いだけで、使い方などが同じ為、 FileIteratorを使って説明していきます。
よって以下ではファイルと書いてある部分をフォルダ、FileをFolderと読み替えて下さい。

FileIteratorは基本的に、
”取り出せるファイルがあるかどうか”の確認と(.hasNext())
”取り出せるファイルを取り出す”こと (.next())
しかできません!

一連の流れとしては、
複数のファイルが入っているFileIteratorのオブジェクトを取得

FileIteratorから取り出せるファイルがあるか? No → 終わり
↓Yes             ↑ループ
FileIteratorからファイルを取り出す

詳しくはコードを交えてみてみましょう。

※なお、FileIteratorには"getContinuationToken()"という関数も用意されているのですが、さらにややこしと判断したため割愛させていただきます。

取り出せるファイルがあるかどうかの確認: hasNext()

FileIteratorから取り出せるファイルがあるかどうかを確認できます。
戻り値は、TrueまたはFalseです。
Trueなら取り出せるファイルがあるということです。
Falseならもうないので、おしまいです。

今回は、Googleドライブにある全てのファイルを取得できる関数(DriveApp.getFiles())を使ってみてみましょう。
この関数については別で紹介しています。

// Googleドライブにある全てのファイルをFileIteratorオブジェクトとして取得
let allFileIterator = DriveApp.getFiles();

// 取り出せるファイルがあるか確認
console.log(allFileIterator.hasNext()); // → TrueかFalseが返ってきます。

ファイルを取り出す: next()

FileIteratorから取り出せるファイルオブジェクトを返します。
それと同時に、FileIterator自体も次のファイルを取り出すための体勢に入ります。

ややこしいですが、つまりファイルAを".next()"で取り出したFileIteratorから再度ファイルAを取り出すことができず、".next()"で取り出せるのは、もしあるなら、ファイルBということになります。

なお、取り出せるファイルがないにも関わらず、この関数を実行するとエラーが発生します。

※ファイル名の確認:ファイルオブジェク.getName() 
詳しくは別で

// Googleドライブにある全てのファイルをFileIteratorオブジェクトとして取得
let allFileIterator = DriveApp.getFiles();

// あるであろうファイルを取り出してみる
let file = allFileIterator.next(); // → ファイルがない場合はエラーが発生
console.log(file.getName()); // → ”ファイルA”:ファイル名を確認

// 再度ファイルを取り出してみる
file = allFileIterator.next();
console.log(file.getName()); // → "ファイルB": ”ファイルA”ではない。次のファイルが取り出された


一連の流れを見てみる!

取り出せるファイルがないにも関わらず、この関数を実行するとエラーが発生するので、
「取り出せるファイルがあるか確認してから 実際にファイルを取り出す」というのが、ここでの一般的な一連の流れだと思います。

ここで、Googleドライブにある全てのファイルが[fileA, fileB]とした上で、下のコードをご覧ください。

// Googleドライブにある全てのファイルをFileIteratorオブジェクトとして取得
let allFileIterator = DriveApp.getFiles();

// ["fileA", fileB]の回

// 取り出せるファイルがあるか確認する
if (!allFileIterator.hasNext()) {
   return;
}
// ファイルを取り出す
let fileA = allFileIterator.next();
console.log(fileA.getName()); // → "fileA"

// [fileA, "fileB"]の回
if (!allFileIterator.hasNext()) {
   return;
}
let fileB = allFileIterator.next();
console.log(fileB.getName()); // → "fileB"

// [fileA, fileB]の回
if (!allFileTerator.hasNext()) {
   return;       // もう取り出せるファイルがないのでここでおしまい。
}
 

上のコードにwhile文を使うと↓

// Googleドライブにある全てのファイルをFileIteratorオブジェクトとして取得
let allFileIterator = DriveApp.getFiles();

while (allFileIterator.hasNext()) { // 取り出せるファイルがあったらループ内に
  let file = allFileIterator.next();
  console.log(file.getName());
}


---------以下ログ------------
-> fileA
-> fileB



この記事が気に入ったらサポートをしてみませんか?