How to zip multiple folders generating multiple .zip files in gulp? - gulp

My folder structure looks like this:
- /projects
- /projects/proj1
- /projects/proj2
- /projects/proj3
- /zips
For each folder in projects (proj1, proj2 and proj3) I want to zip contents of each of those folders and generate proj1.zip, proj2.zip and proj3.zip in /zips folder.
Following example function generates single zip file from proj1 folder
zip = require('gulp-zip');
gulp.task('default', function () {
return gulp.src('./projects/proj1/*')
.pipe(zip('proj1.zip'))
.pipe(gulp.dest('./zips'));
});
But how I can execute such task for each folder in projects? I can get all folders to zip by gulp.src('./projects/*') but what then?

Old question I know and I am pretty new to gulp so this might be considered a hack but I have just been trying to do what you are after and I ended up with this.
My file structure is this:
proj
proj/dist
proj/dist/sub01
proj/dist/sub02
proj/dist/sub03
proj/zipped
And my task ended up like this:
var gulp = require("gulp");
var foreach = require("gulp-foreach");
var zip = require("gulp-zip");
gulp.task("zip-dist", function(){
return gulp.src("./dist/*")
.pipe(foreach(function(stream, file){
var fileName = file.path.substr(file.path.lastIndexOf("/")+1);
gulp.src("./dist/"+fileName+"/**/*")
.pipe(zip(fileName+".zip"))
.pipe(gulp.dest("./zipped"));
return stream;
}));
});
It grabs all the first level contents of ./dist as its source and then pipes it to gulp-foreach.
gulp-foreach looks at each item and I use a plain javascript substr() to get the name of the current item which I store as a variable.
Finally I set a new src using the stored fileName var and pipe the result to gulp-zip using the stored var again as the name of the zipped file.
The result is a structure that looks like this:
proj
proj/dist
proj/dist/sub01
proj/dist/sub02
proj/dist/sub03
proj/zipped
proj/zipped/sub01.zip
proj/zipped/sub02.zip
proj/zipped/sub03.zip
Again, I am a million miles from being an expert but this worked for me and if I understand the question might work for you as well or at least give you some ideas.

Related

How to push a gulp pipeline onto another

I would like to process a series of folders through the build pipeline. For each folder I start another gulp pipeline that will create some source files. Finally I'd like to pipe them all together through the zip() plugin to produce a final artifact.
The following pseudocode shows my approach. However, I cannot push the result of the gulp.src to the current pipeline.
return gulp.src(someFolder)
.pipe(through(function(folder, enc, cb){
// how to add the result of the following line to my
// own pipeline????
this.push(gulp.src(path.join(folder, "whatever"))
.pipe(somePlugin()));
}))
.pipe(zip(....))
.pipe(gulp.dest(....));
Any hints how to combine those pipelines together?
This is exactly what gulp-foreach is intended for. Using that the equivalent of the code you posted would look like this:
var foreach = require('gulp-foreach');
return gulp.src(someFolder)
.pipe(foreach(function(stream, folder) {
return gulp.src(path.join(folder.path, "whatever"))
.pipe(somePlugin());
}))
.pipe(zip(....))
.pipe(gulp.dest(....));
Note that the above will discard all files from the original gulp.src(someFolder). They will not be included in the ZIP. If you want to keep those around as well you can use merge-stream:
var foreach = require('gulp-foreach');
var merge = require('merge-stream');
return gulp.src(someFolder)
.pipe(foreach(function(stream, folder) {
return merge(stream,
gulp.src(path.join(folder.path, "whatever"))
.pipe(somePlugin()));
}))
.pipe(zip(....))
.pipe(gulp.dest(....));

How to dynamically specify destination folder to gulp

I have a folder structure where I keep all my assets similar to this.
-page1
-page1.html
-stylesheets
-page1
-page1style.css
-page2
page2.html
stylesheets
page2
page1style.css
I realize that this isn't the best folder structure but I choose it this way before I could have predicted problems. In my .html files I reference a stylesheet like so /stylesheets/name-of-page/foo.css. Now I am having problems writing a gulp script since all the minified files are being placed at the specified destination folder but have the following structure.
-build
-page1
-stylesheets
-page1.css
when I would like to have something like this
-build
-page1
-page.css
TL;DR or if my question is logic is scrambled : I would like to see the src path of the file at runtime and then perform some string manipulation to calculate its destination.
What you're looking for is gulp-rename:
var gulp = require('gulp');
var rename = require('gulp-rename');
gulp.task('default', function() {
gulp.src('src/**/*')
.pipe(rename(function(file) {
if (file.extname === '.css') {
file.dirname = //change directory to something else
file.basename = //change file name (without extension) to something else
}
}));
});
I also suggest you look into the path module instead of direct string manipulation to adjust the paths of your files.

Dynamic filename in gulp-zip

I try to generate multiple zip files with gulp-zip
packages
- package-1
- package-2
to
build
- package-1.zip
- package-2.zip
At the moment my task looks like this:
gulp.task('zip', function () {
return gulp.src("packages/*")
.pipe(zip("archive.zip"))
.pipe(gulp.dest("build"));
});
This generates a single zip file names archive.zip which contains my two packages.
How to get 2 separate zipfiles?
How to pass the folder name to the zip function?
You can call the zip command twice in your zip task, like so:
gulp.task('zip', function () {
gulp.src("packages/package-1/**")
.pipe(zip("archive-1.zip"))
.pipe(gulp.dest("build"));
return gulp.src("packages/package-2
.pipe(zip("archive-2.zip"))
.pipe(gulp.dest("build"));
});
This will result in 2 zip-files in your build folder. Hope this helps.

Gulp: How to set users home directory in Gulp destination?

Is there a way I can read %USERPROFILE% directory in Gulp task and use it for destination to pipe to?
gulp.task('push-my-repos', function () {
var baseDir = '../Bower-Learning-1';
var dest = 'C://Users//user-1//AppData/Local//MY//Bower//Repos//**';
var src = ['../**/*.*', '!./**/', '!../*.*'];
console.log("%USERPROFILE%");
return gulp.src(src, { base: baseDir})
.pipe(gulp.dest(dest))
});
In this sample task I want to pick "dest" dynamically instead of hard coding so that my colleagues can run this task without changing it.
As stated in the accepted answer, the home directory can be accessed from
process.env.HOME
I made it work with the help of node environment variables.

How to zip up zip files using Gulp Zip

I've started using Gulp JS and must admit I'm finding it really useful.
One of the tasks I need to perform is zip up a collection of folders into individual zip files, one for each folder and then zip all this zipped files up into one single zip file. Using Gulp-Zip I've managed to get this far:
var modelFolders = [
'ELFH_Check',
'ELFH_DDP',
'ELFH_Free'
];
gulp.task('zipModels', function () {
for (var i = 0; i < modelFolders.length; i++) {
var model = modelFolders[i];
gulp.src('**/*', {cwd: path.join(process.cwd(), '/built_templates/' + model) })
.pipe(zip(model + '.zip'))
.pipe(gulp.dest('./built_templates'));
};
});
This works and outputs ELFH_Check.zip, ELFH_DDP.zip and ELFH_Free.zip. However, I then need to zip up these zip files into one zip file called "Templates.zip" and I've not managed to get this task to work:
// zip up model files
gulp.task('zipTemplate', ['zipModels'], function () {
gulp.src('*.zip', {cwd: path.join(process.cwd(), './built_templates/') })
.pipe(zip('Templates_.zip'))
.pipe(gulp.dest('./built_templates'));
});
Does anyone know if this is possible or what I'm doing wrong?
I saw the problem as well, and it seems to be related to the cwd option somehow. I'll investigate further.
After #OverZealous comment, I investigated further and found two issues:
As he said, you need to hint gulp to wait until the end of the dependency task (zipModels), by returning a stream from it. As you have multiple streams, you can use event-stream.merge to return a bundle stream.
The reason why the bundle zip wouldn't work, is because you cwd points to /built_templates/, and the second slash is causing some problem. To work properly, you need to remove the trailing slash, so it should be path.join(process.cwd(), '/built_templates').
IMPORTANT
Anyway, you should avoid temporary files. Gulp philosophy is to try using pipes to avoid IO. In that direction, what you want to do is to cut the intermediary dest steps, merge the streams, zip them, and finally, output them.
Something like that:
var es = require('event-stream');
var modelFolders = [
'ELFH_Check',
'ELFH_DDP',
'ELFH_Free'
];
gulp.task('zipModels', function () {
var zips = [],
modelZip;
for (var i = 0; i < modelFolders.length; i++) {
var model = modelFolders[i];
modelZip = gulp.src('**/*', {cwd: path.join(process.cwd(), '/built_templates/' + model) })
.pipe(zip(model + '.zip'));
// notice we removed the dest step and store the zip stream (still in memory)
zips.push(modelZip);
};
// we finally merge them (the zips), zip them again, and output.
return es.merge.apply(null, zips)
.pipe(zip('templates.zip'))
.pipe(gulp.dest('./'));
});
By the name of your folder (built_templates), it seems you have some other task that will generate the temporary built files. Preferably, you don't want these as well. You should pipe their streams directly to the ZIP stream, a finally, to the bundle-zip stream. By doing that, you would have a simple stream flow, with one disk read, and one disc write at the end, with no temporary files.
If you need them to be different tasks, consider having a function that will generate the stream up to the step before the gulp.dest pipe, and use this function on all subtasks.
Additionally, always try to hint your async tasks by returning a stream, a promise or receiving a callback function, and advise the end of the task.