Search code examples
gruntjsgrunt-contrib-copyasp.net-core-3.1

grunt task copy failing to write the file in the destination


I'm new to gruntjs and struggling to understand why a simple copy file task is not working. Below is my code in Gruntfile.js.

module.exports = function (grunt) {
    "use strict";

    // Project configuration
    grunt.initConfig({
        pkg: grunt.file.readJSON("package.json"),

        // copy other css files
        copy: {
            dist: {
                files: {
                    //expand: true, // required when using cwd
                    //cwd: ['.'], // set working folder / root to copy
                    src: './wwwroot/lib/html5-reset/assets/css/reset.css', // copy all files and subfolders
                    dest: './wwwroot/css/' // destination folder
                }
            }
        }
    });

    grunt.loadNpmTasks("grunt-contrib-copy");

    grunt.registerTask("copyCss", ["copy"]);
};

When I execute the task I'm getting the following error

Loading "Gruntfile.js" tasks...OK
+ copyCss
Running tasks: copy
Running "copy" task
Running "copy:dist" (copy) task
Verifying property copy.dist exists in config...OK
Files: ./wwwroot/lib/html5-reset/assets/css/reset.css -> src
Files: ./wwwroot/css/ -> dest
Options: encoding="utf8", processContent=false, processContentExclude=[], timestamp=false, mode=false
Copying ./wwwroot/lib/html5-reset/assets/css/reset.css -> src
Reading ./wwwroot/lib/html5-reset/assets/css/reset.css...OK
Writing src...ERROR
Warning: Unable to write "src" file (Error code: EISDIR). Used --force, continuing.
Done, but with warnings.
Process terminated with code 0.

Appreciated your help in pinpointing the issue.


Solution

  • The nodejs error EISDIR is described as:

    EISDIR (Is a directory): An operation expected a file, but the given pathname was a directory.

    Configure your Gruntfile.js as shown below instead.

    Gruntfile.js

    module.exports = function (grunt) {
      "use strict";
    
      // Project configuration
      grunt.initConfig({
        pkg: grunt.file.readJSON("package.json"),
    
        copy: {
          dist: {
            expand: true,
            cwd: 'wwwroot/lib/html5-reset/assets/css',
            src: 'reset.css',
            dest: 'wwwroot/css'
          }
        }
      });
    
      grunt.loadNpmTasks("grunt-contrib-copy");
      grunt.registerTask("copyCss", ["copy"]);
    };
    

    Running the following command:

    grunt copyCss
    

    will copy the file named reset.css from the wwwroot/lib/html5-reset/assets/css/ directory to the wwwroot/css/ directory.

    Example Before:

    .
    ├── Gruntfile.js
    ├── node_modules
    │   └── ...
    ├── package.json
    └── wwwroot
        └── lib
            └── html5-reset
                └── assets
                    └── css
                        └── reset.css   <--------------
    

    Example After:

    .
    ├── Gruntfile.js
    ├── node_modules
    │   └── ...
    ├── package.json
    └── wwwroot
        ├── css
        │   └── reset.css               <--------------
        └── lib
            └── html5-reset
                └── assets
                    └── css
                        └── reset.css   <--------------
    

    Edit: Creating a custom task instead of using grunt-contrib-copy

    If you are only wanting to copy one file then using grunt-contrib-copy seems somewhat unnecessary. Consider creating a custom Task instead. For instance:

    Gruntfile.js

    module.exports = function (grunt) {
      "use strict";
    
      grunt.initConfig({
        pkg: grunt.file.readJSON("package.json")
      });
    
      grunt.registerTask('copyCss', 'Copies a single file', function() {
        grunt.file.copy(
          'wwwroot/lib/html5-reset/assets/css/reset.css',
          'wwwroot/css/reset.css'
        )
      });
    
    };
    
    • The aforementioned custom task utilizes grunt's build-in grunt.file.copy method.

    • You may also want to consider adding some error handling to that custom Task too. For instance, you may want to utilize grunt's built-in grunt.file.exists method to check whether the reset.css file exists before proceeding to copy it.