Node.jsで複数フォルダをzipで圧縮
この記事は
Node.jsにて
- archiverを使ったzip圧縮
- child_processを使ったマルチスレッド化
したソースコードが乗っかっているだけ
やりたいこと
HDDのデータを整理するのに、フォルダ毎に圧縮して保存したいな~という需要があった。
Folder ├Folder1 │├file1 │└file2 ├Folder2 │├file1 │└file2 ├Folder3 │├file1 │└file2 ・・・
これを
Folder ├Folder1.zip ├Folder2.zip ├Folder3.zip ・・・
という具合にしたい。 7zipとバッチファイルでなんとかする試みもある。 これはD&Dで圧縮出来てとても便利なので、これを使えばいいと思うが今回はnodejsで作ってみた。
child_processを使ったので、親子で2ファイルある。
- 親:フォルダのリストを作って、子に渡す
- 子:与えられたフォルダの中身をアーカイブ化
使うときはmain.jsとchild.jsを同じ階層に入れてmain.jsを実行
folder ├main.js └child.js
親側 main.js
const fs = require('fs') const child_process = require('child_process') // 対象フォルダ const sourceDir = "/home/raytency/data/" // プロセス数 const cpuNum = 8 // フォルダのリスト let folders = [] function createProc(){ // リストから一つ取り出し let folder = folders[0] let filepath = sourceDir+"\\"+folder folders.shift() // プロセス生成 cproc = child_process.fork("./child",null,{env:{filepath:filepath}}) cproc.on("exit",()=>{ // 子プロセス終了時、リストが残ってたらまた新たにプロセス生成 if(folders.length>0){ createProc() } else { console.log("exit....") } }) } function main(){ // 対象フォルダ内にあるフォルダのリストを作成 let allFiles = fs.readdirSync(sourceDir) folders = allFiles.filter((file)=>{ return fs.statSync(sourceDir+"\\"+file).isDirectory() }) // コア数ぶん子プロセス立ち上げ for(let i=0; i<cpuNum; i++){ createProc() } } main()
子側 child.js
const archiver = require('archiver') const fs = require('fs') const path = require('path') // source: アーカイブ化したいフォルダのパス // dest: 生成したいzipファイルのパス function zipFolder(source, dest){ var archive = archiver.create( 'zip', {zlib: { level: 5 }} ) var output = fs.createWriteStream( dest ); output.on('close', function() { console.log(archive.pointer() + ' total bytes'); }); archive.pipe(output) //ファイルをどんどんついかする let allFiles = fs.readdirSync(source) for(file of allFiles){ //console.log("[file Name] "+file); let stat = fs.statSync(source+"\\"+file) if(stat.isFile()){ archive.file(source+"\\"+file,{name: file}) } if(stat.isDirectory()){ archive.directory(source+"\\"+file, file) } } archive.finalize(); } let dest = process.env.filepath + ".zip" zipFolder(process.env.filepath, dest) console.log(path.basename(process.env.filepath))