Search code examples
jquery-uigulpgruntjsglob

What globbing pattern will exclude a subdirectory except for two other subdirectories inside it?


I am copying over the jQueryUI library from bower. I only want to copy over two themes from their "themes" directory. The theme folders I want to keep are "base" and "ui-lightness".

How can I accomplish this with a globbing pattern?

I've tried this...

gulp.src([
    './bower_components/jqueryui/**',
    '!./bower_components/jqueryui/themes/**(!base/**)'
])

Here is the directory structure:

├── themes
│   ├── base
│   ├── black-tie
│   ├── blitzer
│   ├── cupertino
│   ├── dark-hive
│   ├── dot-luv
│   ├── eggplant
│   ├── excite-bike
│   ├── flick
│   ├── hot-sneaks
│   ├── humanity
│   ├── le-frog
│   ├── mint-choc
│   ├── overcast
│   ├── pepper-grinder
│   ├── redmond
│   ├── smoothness
│   ├── south-street
│   ├── start
│   ├── sunny
│   ├── swanky-purse
│   ├── trontastic
│   ├── ui-darkness
│   ├── ui-lightness
│   └── vader
└── ui
    ├── i18n
    └── minified

Solution

  • Gulp v4.x

    The current gulp docs include an example glob pattern which can be customized to meet your requirement. Try the following:

    gulp.task('copyfoobar', function() {
       gulp.src([
           'bower_components/jqueryui/**', // [1]
           '!bower_components/jqueryui/themes/**', // [2]
           'bower_components/jqueryui/themes/{base,ui-lightness}/**' // [3]
       ], { base: './' } )
       .pipe(gulp.dest('./dist'));
    });
    

    The Array of globs shown above does the following:

    • [1] Matches everything under the bower_components/jqueryui/ directory.
    • [2] Negates the bower_components/jqueryui/themes directory, (and everything in it), from the list created via the previous glob pattern.
    • [3] Adds the bower_components/jqueryui/themes/base and bower_components/jqueryui/themes/ui-lightness directories, (and everything in them), back to the list.

    Note: The solution above assumes that the bower_components directory resides in the same directory as your gulpfile.js, and the target directory is dist.

    Resultant directory tree:

    If you don't want the bower_components directory added to your target/destination directory, (i.e. dist), then set the base option to:

    { base: './bower_components/' }
    

    This will result in something like this:

    .
    └── dist
        └── jqueryui
            ├── themes
            │   ├── base
            │   │   └── ...
            │   └── ui-lightness
            │       └── ...
            └── ...
    

    Where as setting the base option to:

    { base: './' }
    

    results in something like this:

    .
    └── dist
        └── bower_components
            └── jqueryui
                ├── themes
                │   ├── base
                │   │   └── ...
                │   └── ui-lightness
                │       └── ...
                └── ...
    

    Gulp v3.x

    Unfortunately, the example shown above does not work in Gulp version 3.x because Negations (!) were handled differently - they were always done last regardless of the order they were specified in the glob Array. More info of that discussed in issue 837.

    The workaround, (for v.3.x), is to utilize gulp-src-ordered-globs which will allow you to use the same Array of globs as the previous example.

    The code for this will be:

    var gulpSrc = require('gulp-src-ordered-globs'); // require the gulp.src() wrapper.
    
    gulp.task('copyfoobar', function() {
       gulpSrc([ // <-- gulpSrc() used instead of gulp.src() 
           'bower_components/jqueryui/**',
           '!bower_components/jqueryui/themes/**',
           'bower_components/jqueryui/themes/{base,ui-lightness}/**'
       ], { base: './' } )
       .pipe(gulp.dest('./dist'));
    });