Comment copier des répertoires de manière récursive avec gulp?

167

J'essaye de mettre en scène un projet d'un répertoire de travail vers un serveur (même machine). En utilisant le code suivant:

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

Je m'attendrais à voir tous les fichiers copiés. Cependant, cela aplatit la structure des répertoires - tous les répertoires sont copiés mais chaque fichier est placé à la racine/var/www

Gulp semble être un excellent outil de construction, mais la copie d'éléments devrait certainement être un processus simple?

M1ke
la source
9
Pour tout nouveau spectateur lisant cette question, il convient de noter que la réponse la plus élevée ne fonctionne pas pour résoudre la spécification de la question originale de ne pas aplatir les répertoires. Il ne résout les problèmes des gens ont avec pas tous les fichiers à l' intérieur d' un répertoire d'être copié, donc c'est utile!
M1ke
1
Par ne pas aplatir, voulez-vous dire que vous voulez que les répertoires 'css', 'js' et 'src' soient présents /var/www/? Vous pourriez essayer{css,js,src}/**/*
Jason Goemaat
Je sais que l'expansion de glob fonctionne dans gulp, mais je serais confus si cela fonctionnait différemment pour chaque élément en tant que ligne individuelle dans une liste - car l'expansion de glob est essentiellement destinée à s'étendre à une liste avant l'exécution.
M1ke

Réponses:

319

Ce qui suit fonctionne sans aplatir la structure des dossiers:

gulp.src(['input/folder/**/*']).pipe(gulp.dest('output/folder'));

C'est '**/*'la partie importante. Cette expression est un glob qui est un puissant outil de sélection de fichiers. Par exemple, pour copier uniquement les fichiers .js, utilisez:'input/folder/**/*.js'

cancerbero
la source
2
pense que vous avez oublié d'ajouter le gulp.dest. Devrait être.pipe(gulp.dest('output/folder'));
Matthew Sprankle
3
Comment faites-vous cela avec une extension de fichier spécifique?
Chev
1
Pouvez-vous modifier la réponse pour fournir un exemple de l'ensemble de fichiers d'origine? Je ne sais pas comment cela est plus approprié, mais je serais heureux de voir comment cela fonctionne par rapport à la {base:"."}méthode.
M1ke
2
Il est important de noter que la basevaleur par défaut est "dossier" comme indiqué dans cette réponse. En d'autres termes, la base commence là où le motif glob commence. Cela m'a aidé à comprendre où finiraient mes fichiers et c'est aussi pourquoi vous n'avez pas besoin **/*du gulp.destparamètre dans. Gulp prend tout dans le glob et le place dans le dossier dest avec la même structure.
Neil Monroe
3
Cela ne répond pas entièrement à la question posée. C'est une bonne solution pour savoir comment copier correctement de manière récursive, mais cela ne répond pas comment modifier le répertoire de base.
ty1824
173

Il s'avère que pour copier une structure de répertoire complète gulpdoit être fournie avec une base pour votre gulp.src()méthode.

Ainsi gulp.src( [ files ], { "base" : "." })peut être utilisé dans la structure ci-dessus pour copier tous les répertoires de manière récursive.

Si, comme moi, vous oubliez cela, essayez:

gulp.copy=function(src,dest){
    return gulp.src(src, {base:"."})
        .pipe(gulp.dest(dest));
};
M1ke
la source
1
Ajoutez la configuration "cwd" pour définir le répertoire de travail actuel.
Skarllot
3
Si basevous êtes toujours déroutant, jetez un œil à stackoverflow.com/a/35848322/11912 qui fait un excellent travail pour l'expliquer.
James Skemp
60

Donc - la solution de fournir une base fonctionne étant donné que tous les chemins ont le même chemin de base. Mais si vous souhaitez fournir différents chemins de base, cela ne fonctionnera toujours pas.

Une façon de résoudre ce problème était de rendre le début du chemin relatif. Pour votre cas:

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

La raison pour laquelle cela fonctionne est que Gulp définit la base comme étant la fin du premier morceau explicite - le premier * l'amène à définir la base au cwd (ce qui est le résultat que nous voulons tous!)

Cela ne fonctionne que si vous pouvez vous assurer que votre structure de dossiers n'aura pas certains chemins qui pourraient correspondre deux fois. Par exemple, si vous aviez randomjs/au même niveau que js, vous finiriez par faire correspondre les deux.

C'est le seul moyen que j'ai trouvé pour les inclure dans le cadre d'une fonction gulp.src de niveau supérieur. Il serait probablement simple de créer un plugin / une fonction qui pourrait séparer chacun de ces globs afin que vous puissiez spécifier le répertoire de base pour eux, cependant.

ty1824
la source
Je pense que le fait de devoir commencer par plusieurs chemins de base dépasse probablement le cadre de la question. De ma question d'origine, je déplaçais les fichiers vers un chemin absolu, mais le problème se posait toujours, que sans spécifier de base, tous les fichiers de tous mes globs étaient copiés dans un seul répertoire sans que leur hiérarchie existante ne soit suivie.
M1ke
2
@ M1ke C'est vrai, le point principal de votre question ne concernait pas les différents chemins de base. Cependant, vous avez mentionné However it flattens the dir structure - all directories are copied but every file is placed in the root /var/www, et c'est en fait ainsi que j'ai trouvé votre question - je cherchais une solution sur la façon de copier récursivement avec différents chemins de base. Essentiellement, cette solution fonctionne pour votre cas sans avoir à spécifier de base par défaut, mais aussi pour un cas de chemin multi-base, tant que vous pouvez vous assurer que l'étoile principale ne correspond à rien :)
ty1824
6
Cette réponse est exceptionnelle. Il traite spécifiquement de la copie d'un chemin à partir d'un point de départ arbitraire, par exemple. src pourrait être 'assets/subdir/*fonts/*'de copier le répertoire des polices.
Wtower
-4

Si vous souhaitez copier tout le contenu d'un dossier de manière récursive dans un autre dossier, vous pouvez exécuter la commande Windows suivante à partir de gulp:

xcopy /path/to/srcfolder /path/to/destfolder /s /e /y

L' /yoption à la fin est de supprimer le message de confirmation d'écrasement.

Sous Linux, vous pouvez exécuter la commande suivante à partir de gulp:

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

vous pouvez utiliser le plugin gulp-exec ou gulp-run pour exécuter des commandes système à partir de gulp.

Liens connexes:

  1. utilisation de xcopy

  2. gulp-exec et gulp-run

Manoj Amalraj
la source
7
Le problème avec le retour au shell ici est que vous perdriez la possibilité d'exécuter d'autres commandes sur le flux, telles que des outils de compression ou d'analyse.
M1ke