如何使用 Grunt 将文件复制到每个目录?

How to copy a file to every directory with Grunt?

所以我正在构建一个 WP 插件,通常将空 index.html 文件放入每个文件夹中,以防止在主机允许的情况下列出目录。我正在使用 grunt 构建部署就绪包,但我唯一缺少的是这些文件。我有很多文件夹,不想手动创建这些文件。我很乐意创建一个,并让 Grunt 将该文件复制到每个路径。但是怎么办?

不需要额外的 grunt 插件。您的要求可以使用 Grunt 的内置功能来实现。

考虑将 custom Task 添加到您的 Gruntfile.js,如下所示 createEmptyHtmlFiles

Gruntfile.js

module.exports = function(grunt) {

  grunt.initConfig({
    // ...
  });

  /**
   * Custom task to create empty `index.html` file in all folders.
   */
  grunt.registerTask('createEmptyHtmlFiles', function() {

    var fileName = 'index.html',
        contents = '';

    grunt.file.expand({ filter: 'isDirectory' }, 'dist/**/*')
        .forEach(function(dirPath) {
          var htmlFilePath = dirPath + '/' + fileName;
          grunt.file.write(htmlFilePath, contents, { encoding: 'utf8'})
        });
  });

  grunt.registerTask('default', ['createEmptyHtmlFiles']);

};

解释:

  1. 通常,您的 Gruntfile.js 将包含 grunt.initConfig({ ... }); 部分,该部分定义了您要执行的各种任务的配置。这部分应该保持你当前的配置。

  2. 已注册名为 createEmptyHtmlFiles 的自定义任务,它执行以下操作:

    • 将所需的文件名,即 index.html 分配给 fileName 变量,并将空字符串分配给 contents 变量。

    • 接下来我们利用grunt.file.expand to which we pass a globbing pattern。在上面的示例中,提供的 glob 是 'dist/**/*'。 globbing 模式结合 filter: 'isDirectory' 选项实质上获得了 dist 目录中所有文件夹的路径名。

      重要提示:您需要根据您的目录结构更改此 glob 模式。

    • 接下来我们使用 Array 的 forEach 方法迭代每个目录路径名。

    • forEach 循环的每一轮中,我们为 htmlFilePath 变量分配一个新路径名,用于创建结果 index.html 文件的位置。

    • 每个 index.html 文件都是使用 grunt.file.write 创建的。

演示:

  1. 假设项目目录结构如下:

    .
    ├── Gruntfile.js
    ├── dist
    │   ├── a
    │   │   ├── b
    │   │   │   └── 1.txt
    │   │   └── c
    │   │       └── 2.txt
    │   ├── d
    │   │   ├── 3.txt
    │   │   └── e
    │   │       └── 4.txt
    │   └── f
    │       └── g
    │           └── 5.txt
    ├── node_modules
    │   └── ...
    └── package.json
    
  2. 鉴于上面的Gruntfile.js在运行$ grunt之后会变成下面这样:

    .
    ├── Gruntfile.js
    ├── dist
    │   ├── a
    │   │   ├── b
    │   │   │   ├── 1.txt
    │   │   │   └── index.html         <-----
    │   │   ├── c
    │   │   │   ├── 2.txt
    │   │   │   └── index.html         <-----
    │   │   └── index.html             <-----
    │   ├── d
    │   │   ├── 3.txt
    │   │   ├── e
    │   │   │   ├── 4.txt
    │   │   │   └── index.html         <-----
    │   │   └── index.html             <-----
    │   └── f
    │       ├── g
    │       │   ├── 5.txt
    │       │   └── index.html         <-----
    │       └── index.html             <-----
    ├── node_modules
    │   └── ...
    └── package.json
    
    

    注意 dist 目录中的每个文件夹现在都包含一个空的 index.html 文件。

  3. 您可能需要排除 index.html 在特定目录中创建。在这种情况下,我们可以通过传递给 grunt.file.expand 方法的 glob 模式来否定特定目录。

    例如,假设我们在 createEmptyHtmlFiles 任务中配置如下:

    ...
    grunt.file.expand({ filter: 'isDirectory' }, ['dist/**/*', '!dist/a/{b,c}'])
    ...
    

    注意: 这次我们传递一个包含两个 glob 模式的数组。第一个与前面的示例相同,但是第二个以 ! 开头,这将使匹配无效。

    运行 $ grunt 使用上述 glob 模式将导致以下目录结构:

    .
    ├── Gruntfile.js
    ├── dist
    │   ├── a
    │   │   ├── b
    │   │   │   └── 1.txt              
    │   │   ├── c
    │   │   │   └── 2.txt              
    │   │   └── index.html             <-----
    │   ├── d
    │   │   ├── 3.txt
    │   │   ├── e
    │   │   │   ├── 4.txt
    │   │   │   └── index.html         <-----
    │   │   └── index.html             <-----
    │   └── f
    │       ├── g
    │       │   ├── 5.txt
    │       │   └── index.html         <-----
    │       └── index.html             <-----
    ├── node_modules
    │   └── ...
    └── package.json
    
    

    注意 dist 目录中的每个文件夹,不包括文件夹 bc,现在包括一个空的 index.html文件.


btw. 当你说 "empty index.html files" 时,我是按字面意思理解的。但是,如果您确实需要在每个文件中添加一些 html 标记,您可以将其分配给 contents 变量。例如:

contents = '<!DOCTYPE html>\n<html>\n<head></head>\n<body></body>\n</html>';

可是我说"copy a file ..."

在这种情况下,您可以将自定义任务更改为以下内容:

/**
  * Custom task to copy a source `index.html` file in all folders.
  */
 grunt.registerTask('copyFileToFolders', function() {

   var srcFilePath = './path/to/file/to/copy/index.html';

   grunt.file.expand({ filter: 'isDirectory' }, 'dist/**/*')
       .forEach(function(dirPath) {
         grunt.file.copy(srcFilePath, dirPath + '/index.html')
       });
 });

备注:

  • 这利用grunt.file.copy将源文件复制到所有文件夹。

  • 分配给 srcFilePath 变量的路径名应替换为要复制到所有文件夹的实际主 index.html 文件的真实路径名。

  • 根据第一个示例,必须根据需要更改传递给 grunt.file.expand 的 glob 模式。