Googleドライブフォルダーにいくつかのファイルを含むフォルダーがあります。そのフォルダ内のすべてのファイルを圧縮し、同じフォルダ内にZipファイルを作成するGoogle Appsスクリプトを作成したいと考えています。
Utilities.Zip()
関数を含むビデオを見つけましたが、そのAPIリファレンスがありません。どうやって使うの?前もって感謝します。
実際には、それよりもさらに簡単です。ファイルはすでにBlobです(getBlob()を持つものはすべて、Blobを期待する任意の関数に渡すことができます)。したがって、コードは次のようになります。
var folder = DocsList.getFolder('path/to/folder');
folder.createFile(Utilities.Zip(folder.getFiles(), 'newFiles.Zip'));
また、フォルダに同じ名前のファイルが複数ある場合は機能しません... Googleドライブのフォルダはサポートしていますが、Zipファイルはサポートしていません。
これを同じ名前の複数のファイルで機能させるには:
var folder = DocsList.getFolder('path/to/folder');
var names = {};
folder.createFile(Utilities.Zip(folder.getFiles().map(function(f){
var n = f.getName();
while (names[n]) { n = '_' + n }
names[n] = true;
return f.getBlob().setName(n);
}), 'newFiles.Zip'));
DocsList
は廃止されたため、次のコードを使用して、ファイルとサブフォルダーを含むフォルダー全体をZipし、その構造を維持することができます。
var folder = DriveApp.getFolderById('<YOUR FOLDER ID>');
var zipped = Utilities.Zip(getBlobs(folder, ''), folder.getName()+'.Zip');
folder.getParents().next().createFile(zipped);
function getBlobs(rootFolder, path) {
var blobs = [];
var files = rootFolder.getFiles();
while (files.hasNext()) {
var file = files.next().getBlob();
file.setName(path+file.getName());
blobs.Push(file);
}
var folders = rootFolder.getFolders();
while (folders.hasNext()) {
var folder = folders.next();
var fPath = path+folder.getName()+'/';
blobs.Push(Utilities.newBlob([]).setName(fPath)); //comment/uncomment this line to skip/include empty folders
blobs = blobs.concat(getBlobs(folder, fPath));
}
return blobs;
}
getBlobs
関数は、フォルダー内のすべてのファイルの配列を作成し、各ファイル名を相対パスに変更して、zip形式になったときに構造を保持します。
同じ名前の複数のアイテムを含むフォルダーを圧縮するには、次のgetBlob
関数を使用します。
function getBlobs(rootFolder, path) {
var blobs = [];
var names = {};
var files = rootFolder.getFiles();
while (files.hasNext()) {
var file = files.next().getBlob();
var n = file.getName();
while(names[n]) { n = '_' + n }
names[n] = true;
blobs.Push(file.setName(path+n));
}
names = {};
var folders = rootFolder.getFolders();
while (folders.hasNext()) {
var folder = folders.next();
var n = folder.getName();
while(names[n]) { n = '_' + n }
names[n] = true;
var fPath = path+n+'/';
blobs.Push(Utilities.newBlob([]).setName(fPath)); //comment/uncomment this line to skip/include empty folders
blobs = blobs.concat(getBlobs(folder, fPath));
}
return blobs;
}
確かにAPIリファレンスはありません。これに関する問題のリクエストをApps Script issue tracker で開くことができます。しかし、コード補完が示すものから推測して、これが私の理解です:
var folder = DocsList.getFolder('path/to/folder');
var files = folder.getFiles();
var blobs = [];
for( var i in files )
blobs.Push(files[i].getBlob());
var Zip = Utilities.Zip(blobs, 'newFiles.Zip');
folder.createFile(Zip);
しかし、私はこのコードをテストしていないため、機能するかどうかはわかりません。また、Googleの形式に変換されていないファイルでのみ機能することもあれば、そのファイルまたはそのサブセットでのみ機能することもあります。さて、試してみて何か見つけたら、こちらで共有してください。確かに直面する制限の1つはファイルサイズです。Zipファイルが大きくなりすぎると、おそらく機能しません。そうです。この制限もテストする必要があります。
@Hafezが投稿したコードを使用することはできましたが、機能しなかったため、コードを変更する必要がありました。文字列値であり、フォルダーの名前ではないフォルダーIDが必要だったため、最初の3行を追加しました。
_var folderName = DriveApp.getFoldersByName("<folderName>");
var theFolder = folderName.next();
var folderID =theFolder.getId();
var folder = DriveApp.getFolderById(folderID);
var zipped = Utilities.Zip(getBlobs(folder, ''), folder.getName()+'.Zip');
folder.getParents().next().createFile(zipped);
function getBlobs(rootFolder, path) {
var blobs = [];
var files = rootFolder.getFiles();
while (files.hasNext()) {
var file = files.next().getBlob();
file.setName(path+file.getName());
blobs.Push(file);
}
var folders = rootFolder.getFolders();
while (folders.hasNext()) {
var folder = folders.next();
var fPath = path+folder.getName()+'/';
blobs.Push(Utilities.newBlob([]).setName(fPath)); //comment/uncomment this line to skip/include empty folders
blobs = blobs.concat(getBlobs(folder, fPath));
}
return blobs;
}
_
私が経験している唯一の奇妙なことは、スクリプトを実行するとTypeError: Cannot call method "getFiles" of undefined. (line 10, file "Code")
と表示されることです。このスクリプトが置かれている場所をたまたま見たとき、完成した5つのZipファイルもありました。動作しますが、まだエラーが発生します。奇妙な...しかし、このコードは私にとってはうまくいきます。このスレッドのみんなに感謝します。乾杯!