如何使用gulp递归地复制目录?

188

我正在尝试将一个项目从工作目录部署到服务器上(同一台机器)。使用以下代码:

gulp.src([
    'index.php',
    'css/**',
    'js/**',
    'src/**',
])
.pipe(gulp.dest('/var/www/'));

我希望看到所有文件都被复制。但是它会扁平化目录结构 - 所有目录都会被复制,但每个文件都会放在根目录 /var/www 中。

Gulp 看起来是一个很棒的构建工具,但是复制文件应该是一个简单的过程,不是吗?


11
对于任何新的读者,如果你阅读这个问题,请注意:最高票答案不能解决原问题不扁平化目录结构的要求。它可以解决一些人复制不了目录中所有文件的问题,所以还是有用的! - M1ke
2
不进行扁平化,是指您希望“css”、“js”和“src”目录存在于“/var/www/”中吗?您可以尝试使用“{css,js,src}/**/*”。 - Jason Goemaat
我知道在gulp中,glob扩展确实可以工作,但如果它与列表中的每个项目作为单独的行有所不同,我会感到困惑 - 因为glob扩展基本上只是在执行之前扩展为列表。 - M1ke
4个回答

346
以下内容不需要对文件夹结构进行压缩处理:
gulp.src(['input/folder/**/*']).pipe(gulp.dest('output/folder'));

'**/*' 是重要部分。该表达式是一个glob,它是一个功能强大的文件选择工具。例如,只想复制 .js 文件,请使用:'input/folder/**/*.js'


2
你似乎忘记了添加gulp.dest。应该是.pipe(gulp.dest('output/folder')); - Matthew Sprankle
3
如何对具有特定文件扩展名的文件执行此操作? - Chev
3
你能否编辑答案,提供原始文件集的示例?我不确定这样做为什么会更合适,但我很乐意看看它与{base:“。”}方法相比如何工作。 - M1ke
1
我已经针对原始指定的情况进行了测试,并确认将目录数组行项目从格式dir/**更改为dir/**/*无效;文件仍然会被压缩到dest()目录中。 - M1ke
2
需要注意的是,base 的默认值是“folder”,如本答案所示。换句话说,基础路径从 glob 模式开始。这帮助我理解了我的文件最终会在哪里,也是为什么在 gulp.dest 参数中不需要使用 **/* 的原因。Gulp 会将 glob 中的所有内容放入 dest 文件夹,并保持相同的结构。 - Neil Monroe
4
这并没有完全回答提出的问题。这是如何正确地递归复制的良好解决方案,但它没有回答如何修改基础目录的问题。 - ty1824

182

原来要复制完整的目录结构,gulp需要为你的gulp.src()方法设置一个基础路径。

因此,可以在上面的结构中使用gulp.src( [ files ], { "base" : "." })来递归地复制所有目录。

如果像我一样可能会忘记这个设置,则可以尝试:

gulp.copy=function(src,dest){
    return gulp.src(src, {base:"."})
        .pipe(gulp.dest(dest));
};

1
添加“cwd”配置以设置当前工作目录。 - Skarllot
5
如果base仍然让你感到困惑,可以参考https://dev59.com/YlsV5IYBdhLWcg3wuxCM#35848322,它做了很好的解释。 - James Skemp

64

所以,如果所有路径具有相同的基本路径,则提供基本工作的解决方案。但是,如果您想提供不同的基本路径,这仍然无法解决问题。

我解决这个问题的方法之一是使路径开头变为相对路径。 对于您的情况:

gulp.src([
    'index.php',
    '*css/**/*',
    '*js/**/*',
    '*src/**/*',
])
.pipe(gulp.dest('/var/www/'));

这个方法有效的原因是,Gulp将基础路径设置为第一个显式块的末尾 - 开头的 * 导致它将基础路径设置为 cwd(这就是我们都想要的结果!)

只有在确保文件夹结构不会出现某些可能会匹配两次的路径时,此方法才有效。例如,如果您的 randomjs/js 处于同一级别,则会同时匹配上。

这是我发现的唯一一种将它们作为顶层 gulp.src 函数的一部分包含的方法。然而,很可能很容易创建一个插件/函数,以将每个 glob 分离出来,使您可以为它们指定基础目录。


我认为从多个基本路径开始可能超出了问题的范围。从我的原始问题中,我将文件移动到绝对路径,但问题仍然存在,如果没有指定基本路径,则来自所有全局通配符的所有文件都会被复制到单个目录中,而不遵循它们现有的层次结构。 - M1ke
2
@M1ke 是的,你的问题的主要重点并不是针对不同的基本路径。但是,你提到了“然而它会扁平化目录结构 - 所有目录都被复制,但每个文件都放在根目录/var/www中”,这实际上是我找到你的问题的原因 - 我正在寻找如何递归地复制具有不同基本路径的解决方案。本质上,这个解决方案适用于你的情况,而无需指定默认基础路径,但也适用于多基础路径的情况,只要你确保前导星号不匹配任何内容 :) - ty1824
6
这个答案非常出色。它专门涉及从任意起始点复制路径的问题,例如,src可以是'assets/subdir/*fonts/*',以复制字体目录。 - Wtower
我进行了一些调查,发现为了消除不匹配的可能性,您可以使用@(css)/**/*。例如,这将保留文件夹结构,但是@()表示它仅适用于该特定文件夹(您还可以提供多个文件夹)。有关更多信息,请参阅glob的文档。https://www.npmjs.com/package/glob - JacobTheDev

-4
如果您想要递归地将一个文件夹的所有内容复制到另一个文件夹中,您可以从gulp执行以下Windows命令:
xcopy /path/to/srcfolder /path/to/destfolder /s /e /y

/y选项是为了抑制覆盖确认消息。

在Linux中,您可以从gulp执行以下命令:

cp -R /path/to/srcfolder /path/to/destfolder

你可以使用gulp-execgulp-run插件从gulp执行系统命令。

相关链接:

  1. xcopy用法

  2. gulp-execgulp-run


8
回归到shell的问题在于,您将失去在流上运行其他命令的能力,例如压缩或分析工具。但是要注意不改变原意,使内容更加通俗易懂。 - M1ke

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