如何使用Grunt根据相应文件的父文件夹名称重命名文件?

52

我有以下结构:

src/
    modules/
        module1/
            js/
                main.js
            scss/
                main.scss
            index.html
        module2/
            js/
                main.js
            scss/
                main.scss
            index.html

我想运行一个Grunt任务,将它们复制到以下结构中:

dev/
    js/
        module1.js
        module2.js
    css/
        module1.css
        module2.css
    module1.html
    module2.html

有没有使用现有的grunt插件来完成这个操作的方法?如果没有,我该如何实现呢?

6个回答

91

可以使用grunt-contrib-copy插件来完成此操作。

需要注意的主要是,您可以通过使用重命名函数(接收每个文件的目标和源)在程序中更改目标。

下面是一个(有些脆弱的)Gruntfile.js示例,它应该能够复制到您所需的结构:

module.exports = function(grunt) {
  // Project configuration.
  grunt.initConfig({
    copy: {
      main: {
        files: [
          {
            expand: true, 
            cwd: 'src/modules/', 
            src: ['**/*.js'], 
            dest: 'dev/js/', 
            rename: function(dest, src) {
              // use the source directory to create the file
              // example with your directory structure
              //   dest = 'dev/js/'
              //   src = 'module1/js/main.js'
              return dest + src.substring(0, src.indexOf('/')) + '.js';
            }
          },
          {
            expand: true, 
            cwd: 'src/modules/', 
            src: ['**/*.scss'], 
            dest: 'dev/css/', 
            rename: function(dest, src) {
              return dest + src.substring(0, src.indexOf('/')) + '.css';
            }
          },
          {
            expand: true, 
            cwd: 'src/modules/', 
            src: ['**/*.html'], 
            dest: 'dev/', 
            rename: function(dest, src) {
              return dest + src.substring(0, src.indexOf('/')) + '.html';
            }
          }
        ]
      }
    }
  });

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

  // Default task(s).
  grunt.registerTask('default', ['copy']);
};

遇到了相反的情况:需要将文件从一个源移动到不同的文件夹。你的答案解决了我的问题,谢谢! - alice kibin
4
这里还需要注意的是,如果您想在重命名时跳过某些文件,则正确的返回值(默认值)是return dest+'/'+src - 这将导致文件被复制到默认位置。 - guy mograbi
那么,仅仅想要执行一个简单的命令行操作,比如复制文件,你就必须安装一个插件吗?基本上每个操作都需要安装一个插件吗? - Jake Wilson
@Jakobud 不需要,你可以使用内置的Node.js文件处理方法,参见http://nodejs.org/api/fs.html,尽管它们只是低级别的。 - Capaj
1
@Malki 我相信重命名功能实际上是grunt本身的一个特性(而不是特定于grunt-contrib-copy)。我使用grunt@0.4.5grunt-contrib-copy@0.7.0进行了测试,重命名函数仍然被调用。这里是运行重命名函数的grunt代码。如果有简单的方法可以重现您遇到的问题,请告诉我! - Gloopy
显示剩余4条评论

6
现在不再需要仅仅为此使用grunt-contrib-copy,您现在可以利用grunt.file.expandMapping。它具有选项可以仅更改文件扩展名,或定义一个返回输出文件名的函数。

下面是一个示例,演示如何在jade任务中将.jade模板编译为.html文件的files对象:
files: [{
    expand: true, 
    src: "**/*.jade", 
    dest: "<%= distDir %>", 
    cwd: "<%= assetsDir %>/jade", 
    rename: function(dest, matchedSrcPath, options) {
        // return the destination path and filename:
        return (dest + matchedSrcPath).replace('.jade', '.html');
    }
}]

在这种情况下,使用ext:'.html'选项而不是rename选项会更容易,但我在这里使用rename以便您了解它的工作原理。
关于extrename(以及其他)选项的更多信息,请参见grunt.file文档。一些更多的例子可以在这里这里找到。

2
您可以简单地使用以下选项: 展开:true, 扁平化:true 无需自定义重命名回调。

1
如果您想将.coffee文件重命名为.js或类似的文件,则只需进行适当的调整即可;)
sudo npm install grunt-contrib-copy
copy: {
  rename: {
    files: [{
     expand: true,
     dot: true,
     cwd: './app/scripts',
     dest: './app/scripts/',
     src: [
       '**/*.coffee'
     ],
     rename: function(dest, src) {
       console.log(dest + src);
       return dest + src.replace('.coffee','.js');
     }
   }]
  }
},

0

这并不是对你问题的确切回答,但我在这里寻找 使用grunt查找相对目录,所以... 这是我的解决方法

...
base: {
  files:
  [
    {
      expand: true,
      cwd: 'app/design/frontend/',
      src: ['**/Magento_Sales/email-src/*.html'],
      dest: '../../Magento_Sales/email/',
      rename: function(dest, src, expand) {
        src = path.parse(src)
        return path.join(expand.cwd, src.dir, dest, src.base);
      }
    },
  ],
}
...

这一小段代码 path.join(expand.cwd, src.dir, dest, src.base); 只是创建我需要的路径。

expand.cwd = app/design/frontend/

src.dir = <动态文件夹>/Magento_Sales/email-src/

dest = ../../Magento_Sales/email/

src.base = <文件>.html

将它们组合起来得到:app/design/frontend/<公司>/<主题>/Magento_Sales/email/<文件>.html

对于我的情况,现在可以将HTML邮件编译到相对目标文件夹中了。


0

我想将文件保存在根目录下创建的min文件夹中,这样更容易将插件文件夹移动到另一个项目中:

-- Plugins/    
     -- bootstrap/                
            -- bootstrap.js
            -- bootstrap.css
            -- min/
                 -- bootstrap.min.js
                 -- bootstrap.min.css

我在这个页面上找到了解决方案,现在分享出来,希望能帮助其他人:

uglify: {
    options: {
        mangle: true
    },
    dynamic_mappings: {
        // Grunt will search for "**/*.js" under "Plugins/" when the "uglify" task
        // runs and build the appropriate src-dest file mappings then, so you
        // don't need to update the Gruntfile when files are added or removed.
        files: [
            {
                expand: true,     // Enable dynamic expansion.
                cwd: 'Plugins/',  // Src matches are relative to this path.
                src: ['**/*.js', '!**/*.min.js'], // Pattern to match (ignore .min files)
                dest: '/min/',     // Destination path prefix.
                ext: '.min.js',   // Dest filepaths will have this extension.
                extDot: 'last',   // Extensions in filenames begin after the first dot
                rename: function( dest, matchedPath, options ) {

                    Pathname = matchedPath.substring( 0, matchedPath.indexOf('/') );
                    Filename = matchedPath.replace( Pathname, '' );

                    //Return "Plugins / plugin_folder / min / file_name.min.js"
                    return options.cwd + Pathname + dest + Filename;
                }
            },
        ],
    },
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接