[deployment] How do I copy directories recursively with gulp?

I am trying to stage a project from a working directory to a server (same machine). Using the following code:

gulp.src([
    'index.php',
    'css/**',
    'js/**',
    'src/**',
])
.pipe(gulp.dest('/var/www/'));

I would expect to see all the files copied. However it flattens the dir structure - all directories are copied but every file is placed in the root /var/www

Gulp seems like a great build tool but copying items should be a simple process surely?

This question is related to deployment gulp

The answer is


If you want to copy the entire contents of a folder recursively into another folder, you can execute the following windows command from gulp:

xcopy /path/to/srcfolder /path/to/destfolder /s /e /y

The /y option at the end is to suppress the overwrite confirmation message.

In Linux, you can execute the following command from gulp:

cp -R /path/to/srcfolder /path/to/destfolder

you can use gulp-exec or gulp-run plugin to execute system commands from gulp.

Related Links:

  1. xcopy usage

  2. gulp-exec and gulp-run


The following works without flattening the folder structure:

gulp.src(['input/folder/**/*']).pipe(gulp.dest('output/folder'));

The '**/*' is the important part. That expression is a glob which is a powerful file selection tool. For example, for copying only .js files use: 'input/folder/**/*.js'


So - the solution of providing a base works given that all of the paths have the same base path. But if you want to provide different base paths, this still won't work.

One way I solved this problem was by making the beginning of the path relative. For your case:

gulp.src([
    'index.php',
    '*css/**/*',
    '*js/**/*',
    '*src/**/*',
])
.pipe(gulp.dest('/var/www/'));

The reason this works is that Gulp sets the base to be the end of the first explicit chunk - the leading * causes it to set the base at the cwd (which is the result that we all want!)

This only works if you can ensure your folder structure won't have certain paths that could match twice. For example, if you had randomjs/ at the same level as js, you would end up matching both.

This is the only way that I have found to include these as part of a top-level gulp.src function. It would likely be simple to create a plugin/function that could separate out each of those globs so you could specify the base directory for them, however.