Copy all files from directory to another with Grunt.js copy - javascript

I'm trying to copy all the files in a directory to another directory as part of my build process. It works fine for individual files that I specify explicitly but when I try to copy the whole directory it does weird things like copies the full directory structure (or nothing at all). Here is the relevant part from my GruntFile.js:
copy: {
myvoice: {
files: [
{ src:"src/html/index.html", dest:"dist/myvoice/index.html" },
{ src:"src/html/css/style.css", dest:"dist/myvoice/css/style.css" },
{ src:"src/html/js/require.js", dest:"dist/myvoice/js/require.js" },
{ src:"build/myvoice/main.js", dest:"dist/myvoice/js/main.js" },
{ src:"src/html/css/fonts/*", dest:"dist/myvoice/css/fonts/" }
]
}
},
Specifically it's the last line that I can't get to work:
{ src:"src/html/css/fonts/*", dest:"dist/myvoice/css/fonts/" }

The flatten: true option as in this answer might work for some cases, but it seems to me that the more common requirement (as in my case) is to copy a folder and its sub-folder structure, as-is, to dest. It seems that in most cases if you have sub-folders, they are probably being referenced that way in code. The key to doing this is the cwd option, which will preserve folder structure relative to the specified working directory:
copy: {
files: {
cwd: 'path/to/files', // set working folder / root to copy
src: '**/*', // copy all files and subfolders
dest: 'dist/files', // destination folder
expand: true // required when using cwd
}
}

This task will maintain folder structure if you specify a file glob. What you want is the flatten option which will remove the structure.
{
expand: true,
flatten: true,
src: ['src/html/css/fonts/**'],
dest: 'dist/myvoice/css/fonts/',
filter: 'isFile'
}
Find the rest of the available options in the Github repo. Hope this helps.

I would like to add that changing the format of the glob in src will modify how the copy works.
As pointed out by bmoeskau above, the following will copy everything inside dist/ and move it to path/to/dir (overwriting the destination if it already exists).
copy: {
files: {
expand: true,
dest: 'path/to/dir',
cwd: 'dist/',
src: '**'
}
}
Note however, that:
copy: {
files: {
expand: true,
dest: 'path/to/dir',
cwd: 'dist/',
src: '*'
}
}
Will only copy files inside dist/ as well as directories, but will not copy the contents of those directories to the destination.
Also, the following with src: '*/*' will only copy directories with contents inside dist/. That is, files just inside dist/ will not be copied.
copy: {
files: {
expand: true,
dest: 'path/to/dir',
cwd: 'dist/',
src: '*/*'
}
}
Finally, same as above, but src: '**/**' will copy only files inside dist/ as well as files inside dist/ subdirectories to path/to/dir. So there will be no folders inside the destination.
copy: {
files: {
expand: true,
dest: 'path/to/dir',
cwd: 'dist/',
src: '*/*',
flatten: true,
filter: 'isFile'
}
}

Had to use egdy instead curly braces for the files segment (in Coffeescript)...
copy: {
files: [
cwd: 'path/to/files'
src: '**/*'
dest: 'dist/files'
expand: true
]
}

If you are developing with angular yeoman , then this is the better way to copy with grunt.
expand: true is required when using cwd. <%= yeoman.app %> is just the app route ('.').
{
expand: true,
cwd: '<%= yeoman.app %>/data',
dest: '<%= yeoman.dist %>/data',
src: ['**']
}

Related

How to prevent grunt uglify to override destination folder

I am trying to setup my grunt file to not to override some folders inside the destination folders, but I couldn't figure out how.
My structure
Basically I have 2 folders:
htdocs
htdocs_src
htdocs_src is the folder we use to develop things, and then we run a watch task that copies all the code to htdocs folder.
My problem
We add some libraries directly on the htdocs folder, so we don't want them to be touched by grunt uglify task... The problem is that it is not happening.
The task is configured this way:
uglify: {
options : {
beautify: false,
report: "min",
mangle: {
except: ['jQuery']
},
exclude: ['!/ifc-easy-checkout*/**/*', '!/ifc-events*/**/*', '!/ifc-vendors*/**/*'],
compress: {
global_defs: {
"DEBUG": false
}/*,
dead_code: true*/
}
},
target: {
cwd: '<%= dirs.GENERATED_JS %>',
src: ['**/*.js'],
dest: '<%= dirs.GENERATED_JS %>',
expand: true
},
},
where on the exclude property I try to say to the plugin not to override these folders, but it doesn't work.
I am currently using grunt-contrib-uglify 2.0.0
I tried several different solutions, such as changing the exclude property for exceptionsFiles, but then it searched for these folders inside the htdocs_src, since it is not there, it doesn't work (but it isn't what I want, once what I need is to avoid some folders to be overriden inside the destination folder).
Any ideas how to setup this plugin?
Try putting the excluded files in the src and remove the exclude tag
target: {
cwd: '<%= dirs.GENERATED_JS %>',
src: ['**/*.js','!/ifc-easy-checkout*/**/*', '!/ifc-events*/**/*', '!/ifc-vendors*/**/*'],
dest: '<%= dirs.GENERATED_JS %>',
expand: true
},

Compiling SASS files using Grunt creates an unnecessary folder

So I have been trying to create my first compiled css files using grunt and sass, and i am having a problem that I cant figure it out.
Every time that I run the sass task, an unnecessary "sass" folder is created inside of my css folder:
This is how it looks:
module.exports = function(grunt) {
// Project configuration.
grunt.initConfig({
watch:{
sass:{
files:['sass/*.scss'],
task:['sass']
}
},
sass: {
dist: {
files: [{
expand: true,
cwd: '',
src: ['sass/*.scss'],
dest: 'css/',
ext: '.css'
}]
}
}
});
grunt.loadNpmTasks('grunt-sass');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.registerTask('default', ['sass']);
};
And this is how my folder looks after I run the task:
/SASS/somefile.scss
/CSS/SASS/somefile.css
The SASS folder it should not be there, the result i expect is:
/SASS/somefile.scss
/CSS/somefile.css
Thanks in advance!
The problem is due to your parameters for building the files object dynamically. You need to set the cwd parameter: "All src matches are relative to (but don't include) this path."
files: [{
expand: true,
cwd: 'sass/',
src: '*.scss',
dest: 'css/',
ext: '.css'
}]
Create a SASS folder under your CSS folder. Your somefile.scss file move into SASS folder then run.
like as :
CSS/
SASS/somefile.scss

Minified all images - Grunt

I have more than 100 images in my images/ folder.
Here is my imagemin - Grunt Config
// The following *-min tasks produce minified files in the dist folder
imagemin: {
dist: {
files: [{
expand: true,
cwd: '<%= config.app %>/images',
src: '{,*/*/}*.{gif,jpeg,jpg,png,ico}',
dest: '<%= config.dist %>/images'
}]
}
}
When I run grunt build I saw this
Running "imagemin:dist" (imagemin) task
Minified 7 images (saved 492.79 kB)
Only 7 of my images got minified. Not all.
I've tried changing the * around in a diff combination, but so far - no luck.
src: '{,*/*/}*.{gif,jpeg,jpg,png,ico}'
How do I fix my src to minified everything in my images folder ?
I think the problem might be in the src globbing pattern. The pattern you are using only matches those images that are in the cwd root or in a two levels deep ones ({,*/*/}).
If you want all the images in the cwd directory to be minified regardless the levels of subdirectories they reside, you should use the **/* globbing pattern instead:
imagemin: {
dist: {
files: [{
expand: true,
cwd: '<%= config.app %>/images',
src: '**/*.{gif,jpeg,jpg,png,ico}',
dest: '<%= config.dist %>/images'
}]
}
}

Transforming multiple JSX files

Is there a way to specify multiple source -> destination mappings when transforming jsx files to js files using browserify in grunt?
I have the following in Gruntfile.js that supports a single file transformation, but I was hoping to be able to specify a second mapping for another file. I know I can map based on wild card into a single combined destination file. However, that is not what I want since I don't want an "all or nothing" include of the react components on my various pages. Some of the components only apply to a few pages and should not be included everywhere.
browserify: {
options: {
transform: [ require('grunt-react').browserify ]
},
//How do I map a second file here without a wild card?
client: {
src: ['react_components/src/component1.jsx'],
dest: 'react_components/build/component1.js'
}
}
Essentially what I hoped for is a way to provide an array of src-dest mappings in the same task in order to create multiple destination files:
client: [{
src: ['react_components/src/component1.jsx'],
dest: 'react_components/build/component1.js'
}]
Something like the above json
As for me, I do not use browserify, I use grunt-react and react-tools. grunt react allows user to define dynamic_mappings, based on regular expressions, something like this:
//Gruntfile.js
grunt.initConfig({
react: {
dynamic_mappings: {
files: [
/* Controllers compiling. */
{
expand: true,
cwd: './app/scripts/controllers/src',
src: ['**/*.jsx'],
dest: './app/scripts/controllers/dest',
ext: '.js'
},
/* ui-components compiling */
{
expand: true,
cwd: './app/scripts/ui-components/src',
src: ['**/**.jsx'],
dest: './app/scripts/ui-components/dest',
ext: '.js'
},
/* JSX test compiling */
{
expand: true,
cwd: './test/ui-components/src',
src: ['**/**.jsx'],
dest: './test/ui-components/dest',
ext: '.test.js'
}
]
}
}
});

Reference files from dynamic object

I am working on a Gruntfile, and am having difficulty getting a copy task to work the way I want.
I have an Uglify task defined using a dynamic file object like:
uglify: {
files: {
expand: true,
cwd: 'src',
src: [
'some/path/file1.js',
'another/path/file2.js'
],
dest: 'dst',
ext: '.min.js'
}
}
This task works great, and I get my files written out as 'dst/some/path/file1.min.js' and 'dst/another/path/file2.min.js'.
I am working on a copy task, where I would like to copy the files I just built somewhere else. Rather than redefining the rule, I would like to reference the file set with a template.
If I use
copy: {
deploy: {
src: '<%= uglify.files %>',
dest: 'deploy/'
}
}
then I get the
Warning: Object # has no method 'indexOf'
error.
For various reasons beyond the scope of this question, globbing tricks won't work for the deploy.
So, in a copy task, how can I reference the set of files that another task just created?
You have files: {} as an object. It should be an array files: [].
uglify: {
files: [{
expand: true,
cwd: 'src',
src: [
'some/path/file1.js',
'another/path/file2.js'
],
dest: 'dst',
ext: '.min.js'
}]
}
The src on copy config expected to be string or array, but you set an object on it, and when grunt tries to apply indexof method on the src of copy task, error will be the result. you can avoid this by setting uglify.files as array of objects, like this:
uglify: {
files: [{
expand: true,
cwd: 'src',
src: [
'some/path/file1.js',
'another/path/file2.js'
],
dest: 'dst',
ext: '.min.js'
}]
}
Then, it will pass the error but you goal won't meet. you need to select dest of uglify as src for copy. the solution is the grunt method, TEMP FILES, you should set uglify dest in a temp path and then select what you need from there as src of copy task. something like this:
copy:{
deploy:{
files: [{
expand: true,
cwd: 'dst'
src: '**/*.min.js'
dest: 'deploy'
}]
}
}

Categories