Jak rekurencyjnie kopiować katalogi za pomocą gulp?

167

Próbuję przenieść projekt z katalogu roboczego na serwer (ten sam komputer). Używając poniższego kodu:

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

Spodziewałbym się, że wszystkie pliki zostaną skopiowane. Jednak spłaszcza strukturę katalogu - wszystkie katalogi są kopiowane, ale każdy plik jest umieszczany w katalogu głównym/var/www

Gulp wydaje się świetnym narzędziem do budowania, ale kopiowanie elementów z pewnością powinno być prostym procesem?

M1ke
źródło
9
Każdemu nowym widzom czytającym to pytanie należy zauważyć, że najwyższa głosowana odpowiedź nie rozwiązuje pierwotnej specyfikacji pytania dotyczącej nie spłaszczania katalogów. Rozwiązuje problemy, które ludzie mają z nie kopiowaniem wszystkich plików w katalogu, więc jest to przydatne!
M1ke
1
Nie spłaszczając, masz na myśli, że chcesz, aby katalogi „css”, „js” i „src” były obecne w /var/www/? Możesz spróbować{css,js,src}/**/*
Jason Goemaat
Wiem, że ekspansja glob działa wewnątrz gulp, ale byłbym zdezorientowany, gdyby działało inaczej dla każdego elementu jako indywidualnej linii na liście - ponieważ rozszerzenie glob ma po prostu rozwinąć się do listy przed wykonaniem.
M1ke

Odpowiedzi:

319

Poniższe działa bez spłaszczania struktury folderów:

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

To '**/*'jest ważna część. To wyrażenie to glob, który jest potężnym narzędziem do wybierania plików. Na przykład, aby skopiować tylko pliki .js, użyj:'input/folder/**/*.js'

rakbero
źródło
2
myślę, że zapomniałeś dodać plik gulp.dest. Powinno być.pipe(gulp.dest('output/folder'));
Matthew Sprankle
3
Jak to zrobić z określonym rozszerzeniem pliku?
Chev
1
Czy możesz edytować odpowiedź, aby podać przykład oryginalnego zestawu plików? Nie jestem pewien, jak to jest bardziej odpowiednie, ale z przyjemnością przyjrzę się, jak to działa w porównaniu z {base:"."}metodą.
M1ke
2
Należy zauważyć, że basedomyślną nazwą jest „folder”, jak podano w tej odpowiedzi. Innymi słowy, podstawa zaczyna się tam, gdzie zaczyna się wzór globu. Pomogło mi to zrozumieć, gdzie skończą się moje pliki i dlatego nie potrzebujesz parametru **/*w tym gulp.destparametrze. Gulp pobiera wszystko z globu i umieszcza w folderze dest o tej samej strukturze.
Neil Monroe
3
To nie w pełni odpowiada na zadane pytanie. To fajne rozwiązanie, jak poprawnie kopiować rekursywnie, ale nie odpowiada, jak zmodyfikować katalog podstawowy.
ty1824
173

Okazuje się, że aby skopiować kompletną strukturę katalogów, gulptrzeba mieć bazę dla swojej gulp.src()metody.

Więc gulp.src( [ files ], { "base" : "." })może być użyty w powyższej strukturze do rekurencyjnego kopiowania wszystkich katalogów.

Jeśli tak jak ja możesz o tym zapomnieć, spróbuj:

gulp.copy=function(src,dest){
    return gulp.src(src, {base:"."})
        .pipe(gulp.dest(dest));
};
M1ke
źródło
1
Dodaj konfigurację „cwd”, aby ustawić bieżący katalog roboczy.
Skarllot
3
Jeśli basenadal cię to dezorientuje, spójrz na stackoverflow.com/a/35848322/11912, który świetnie to wyjaśnia.
James Skemp,
60

A więc - rozwiązanie polegające na zapewnieniu bazy działa, biorąc pod uwagę, że wszystkie ścieżki mają tę samą ścieżkę podstawową. Ale jeśli chcesz zapewnić różne ścieżki podstawowe, to nadal nie zadziała.

Jednym ze sposobów rozwiązania tego problemu było zrobienie względnego początku ścieżki. W Twoim przypadku:

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

Powodem, dla którego to działa, jest to, że Gulp ustawia podstawę jako koniec pierwszego jawnego fragmentu - wiodący * powoduje, że ustawia podstawę na cwd (co jest wynikiem, którego wszyscy chcemy!)

Działa to tylko wtedy, gdy możesz upewnić się, że struktura folderów nie będzie miała pewnych ścieżek, które mogłyby pasować dwukrotnie. Na przykład, gdybyś miał randomjs/ten sam poziom co js, w końcu dopasowałbyś oba.

To jedyny sposób, w jaki znalazłem, aby uwzględnić je jako część funkcji gulp.src najwyższego poziomu. Prawdopodobnie byłoby łatwo stworzyć wtyczkę / funkcję, która mogłaby oddzielić każdą z tych globów, abyś mógł jednak określić dla nich katalog podstawowy.

ty1824
źródło
Myślę, że konieczność rozpoczynania od wielu ścieżek bazowych prawdopodobnie wykracza poza zakres pytania. Z mojego pierwotnego pytania przenosiłem pliki do ścieżki bezwzględnej, ale nadal występował problem polegający na tym, że bez określenia bazy wszystkie pliki ze wszystkich moich globów były kopiowane do jednego katalogu bez przestrzegania ich istniejącej hierarchii.
M1ke
2
@ M1ke To prawda, główny punkt twojego pytania nie był skierowany na różne ścieżki bazowe. Jednak wspomniałeś However it flattens the dir structure - all directories are copied but every file is placed in the root /var/www, i tak właśnie znalazłem twoje pytanie - szukałem rozwiązania, jak kopiować rekurencyjnie z różnymi ścieżkami bazowymi. Zasadniczo to rozwiązanie działa dla twojego przypadku bez konieczności określania domyślnej podstawy, ale także dla przypadku ścieżki z wieloma bazami, o ile możesz upewnić się, że wiodąca gwiazda nic nie pasuje :)
ty1824
6
Ta odpowiedź jest wyjątkowa. Dotyczy w szczególności kopiowania ścieżki z dowolnego punktu początkowego, np. src mogłoby polegać 'assets/subdir/*fonts/*'na skopiowaniu katalogu czcionek.
Wtower
-4

Jeśli chcesz rekurencyjnie skopiować całą zawartość folderu do innego folderu, możesz wykonać następujące polecenie systemu Windows z gulp:

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

/yOpcja na końcu jest do tłumienia nadpisywania wiadomość z potwierdzeniem.

W Linuksie możesz wykonać następujące polecenie z gulp:

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

Możesz użyć wtyczki gulp-exec lub gulp-run do wykonywania poleceń systemowych z gulp.

Powiązane linki:

  1. użycie xcopy

  2. gulp-exec i gulp-run

Manoj Amalraj
źródło
7
Problem z powrotem do powłoki polega na tym, że utracisz możliwość uruchamiania innych poleceń w strumieniu, takich jak narzędzia do kompresji lub narzędzi analitycznych.
M1ke