使用Grunt.js复制一个目录中的所有文件到另一个目录

96

我正在尝试将一个目录中的所有文件复制到另一个目录作为构建过程的一部分。对于我明确指定的单个文件,它可以正常工作,但是当我尝试复制整个目录时,它会做一些奇怪的事情,比如复制整个目录结构(或者根本不复制)。这是来自我的 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/" }
    ]
  }
},

具体来说,我无法让最后一行工作:

      { src:"src/html/css/fonts/*", dest:"dist/myvoice/css/fonts/" }
5个回答

159

flatten: true选项(如此答案中所述)可能适用于某些情况,但在我看来,更常见的需求(与我的情况相同)是将文件夹及其子文件夹结构完全复制到dest。如果有子文件夹,则它们在代码中很可能以这种方式引用。实现这一点的关键是cwd选项,它将与指定的工作目录相对保留文件夹结构:

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
  }
}

谢谢 - 你说得对,这个答案更符合我提问时的需求。我已经学会如何处理之前答案所造成的扁平化问题,但它确实很烦人。 - Evan Hobbs
15
我为此浪费了一个多小时...如果你使用了 cwd 选项,请确保将 expand:true 打开。如果不设置 expand:true,则 cwd 将无法正常工作。 - ducin
2
我必须确保目录路径以 '/' 结尾,并添加 flatten: false 才能使其正常工作。 - Samuel Rossille
这就是我在寻找的,我一直在使用 **,谢谢你。 - Someone

46

如果您指定一个文件匹配模式,此任务将保持文件夹结构。如果您想要移除结构,则需要使用 flatten 选项。

{
    expand: true,
    flatten: true,
    src: ['src/html/css/fonts/**'],
    dest: 'dist/myvoice/css/fonts/',
    filter: 'isFile'
}

Github仓库中查找其余可用选项。希望这能帮到你。


26

我想补充一点,改变 srcglob 的格式将会修改复制的方式。

正如上面 bmoeskau 指出的那样,下面的命令将会复制 dist/所有内容path/to/dir(如果目标文件夹已存在,则覆盖它)。

copy: {
  files: {
    expand: true,
    dest: 'path/to/dir',
    cwd: 'dist/',
    src: '**'
  }
}

然而请注意:

copy: {
  files: {
    expand: true,
    dest: 'path/to/dir',
    cwd: 'dist/',
    src: '*'
  }
}

只会复制 dist/ 内部的文件和目录,但不会将这些目录的内容复制到目标位置。

此外,使用 src: '*/*' 的情况下,只会复制 dist/ 内带有内容的目录。也就是说,仅位于 dist/ 下面的文件不会被复制。

copy: {
  files: {
    expand: true,
    dest: 'path/to/dir',
    cwd: 'dist/',
    src: '*/*'
  }
}

最后,与上面一样,但是src: '**/**'将仅复制dist/内部以及dist/子目录中的文件到path/to/dir。因此,目标文件夹内不会有任何文件夹。

copy: {
  files: {
    expand: true,
    dest: 'path/to/dir',
    cwd: 'dist/',
    src: '*/*',
    flatten: true,
    filter: 'isFile'
  }
}

4
很好的解释!+1 - myrocode
3
比起GitHub上的文档,我更喜欢例子。 - wukong
+1 是否有惯例规定星号的数量应该表示什么,例如 ** 是否总是表示文件和目录,而 * 只表示文件? - CodyBugstein
1
bash手册中得知:两个相邻的*作为一个模式将匹配__所有文件__和零个或多个__目录和子目录__。如果后面跟着一个/,则两个相邻的*将仅匹配__目录和子目录__。 - Jorge Bucaran
1
** 匹配 _所有_,而 **/ 匹配目录和子目录(不包括文件)。 - Jorge Bucaran

2

在Coffeescript中,必须使用egdy而不是花括号来表示文件段...

copy: {
  files: [
    cwd: 'path/to/files'
    src: '**/*'
    dest: 'dist/files'
    expand: true
  ]
}

0

如果你正在使用Angular Yeoman进行开发,那么这是使用Grunt复制的更好方式。 在使用cwd时需要扩展:true。<%= yeoman.app %>只是应用程序路径('.')。

 {
    expand: true,
     cwd: '<%= yeoman.app %>/data',
     dest: '<%= yeoman.dist %>/data',
     src: ['**']
    }

虽然这段代码片段可能解决了问题,但包括解释真的有助于提高您的帖子质量。请记住,您正在为未来的读者回答问题,而这些人可能不知道您的代码建议原因。同时,请尽量不要在代码中添加过多的解释性注释,因为这会降低代码和解释的可读性! - Blue

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