Jak skopiować-scalić dwa katalogi?


112

Mam dwa katalogi obrazów i obrazy2 o tej strukturze w systemie Linux:

/images/ad  
/images/fe  
/images/foo  

... i inne 4000 folderów

a drugi jest jak:

/images2/ad  
/images2/fe  
/images2/foo

... i inne 4000 folderów

Każdy z tych folderów zawiera obrazy, a nazwy katalogów pod obrazami i obrazami2 są dokładnie takie same, jednak ich zawartość jest inna. Następnie chcę wiedzieć, jak mogę skopiować-scalić obrazy / images2 / ad do obrazów / reklamy, obrazy / images2 / foo do obrazów / foo i tak dalej ze wszystkimi 4000 folderami ..


1
czy pliki końcowe mają takie same nazwy w obu katalogach?
— Simply_Me

Nie ... na przykład w obrazach / reklamach są 1.jpg, 2.jpg i 3.jpg. Ale na zdjęciach 2 / reklama są 4.jpg i 5.jpg
— ssierral

4
@AmirAliAkbari, nie sądzę, że jest to duplikat - drugie pytanie w zasadzie brzmi: „czy mv łączy się?” (odpowiedź: nie). To pytanie dotyczy sposobu łączenia 2 hierarchii katalogów.
— maxschlepzig

Odpowiedzi:


173

To jest zadanie dla rsync . Nie ma korzyści z robienia tego ręcznie za pomocą pętli powłoki, chyba że chcesz przenieść plik zamiast go skopiować.

rsync -a /path/to/source/ /path/to/destination

W Twoim przypadku:

rsync -a /images2/ /images/

(Zwróć uwagę, że slash będzie włączony images2, w przeciwnym razie zostanie skopiowany /images/images2).

Jeśli obrazy o tej samej nazwie istnieją w obu katalogach, powyższe polecenie zastąpi /images/SOMEPATH/SOMEFILEje /images2/SOMEPATH/SOMEFILE. Jeśli chcesz zastąpić tylko starsze pliki, dodaj opcję -u. Jeśli chcesz zawsze zachować wersję /images, dodaj opcję --ignore-existing.

Jeśli chcesz przenieść pliki /images2z rsync, możesz przekazać tę opcję --remove-source-files. Następnie rsync kopiuje kolejno wszystkie pliki i po zakończeniu usuwa każdy plik. Jest to o wiele wolniejsze niż przenoszenie, jeśli katalog źródłowy i docelowy znajdują się w tym samym systemie plików.


14
..dodaj -P, jeśli chcesz zobaczyć postępy.
— Meetai.com

1
Dodam, że nie ma żadnych korzyści z korzystania ze skomplikowanych pętli powłoki tu nawet jeśli nie chcesz, aby przenieść je zamiast kopiowania ich-w tym przypadku po prostu użyć rsync, a następnie rm -r /images.
— Wildcard

1
Chciałbym również zauważyć, że ważne jest dołączenie ukośników końcowych dla każdego katalogu . Na przykład, jeśli po prostu uruchomiłeś rsync -a images images2, po prostu skopiuje obrazy2 do obrazów zamiast ich scalania.
— Kyle Challis

1
@ s3cur3 Oh. Od 2 do (domyślnie) 1. To nieintuicyjne. Dzięki, naprawiłem swoją odpowiedź.
— Gilles

1
@MaxCoplan Nie. Rsync nie jest narzędziem interaktywnym.
— Gilles

43

Najlepszym wyborem, jak już napisano, jest oczywiście rsync. Niemniej jednak również unison byłby świetnym oprogramowaniem do wykonywania tej pracy. Oba mogą być używane w kilku systemach operacyjnych.

Rsync

rsync synchronizuje w jednym kierunku od źródła do miejsca docelowego. Dlatego następujące oświadczenie

rsync -avh --progress Source Destination

synchronizuje wszystko od źródła do miejsca docelowego . Scalony folder znajduje się w lokalizacji docelowej .

-a oznacza „archiwizuj” i kopiuje wszystko rekurencyjnie od źródła do miejsca docelowego, zachowując prawie wszystko.

-v daje więcej danych wyjściowych („pełne”).

-h dla czytelnego dla człowieka.

- postęp, aby pokazać, ile pracy zostało wykonane.

Jeśli chcesz tylko zaktualizować do docelowego folderu z nowszych plików z folderu źródłowego:

rsync -avhu --progress source destination

Unisono

unison synchronizuje w obu kierunkach. Dlatego następujące oświadczenie

unison Source Destination

synchronizuje oba katalogi w obu kierunkach i ostatecznie źródło równa się celowi To tak, jakby dwukrotnie wykonać rsync ze źródła do dest i odwrotnie.

Bardziej zaawansowane zastosowania można znaleźć na stronach podręcznika użytkownika lub w następujących witrynach:

  1. https://www.cis.upenn.edu/~bcpierce/unison/
  2. https://rsync.samba.org/

2
Chcę wspomnieć, że poprawna ścieżka do folderu powinna mieć końcowy ukośnik na końcu rsync -avh --progress source/ destination/, w przeciwnym razie folder źródłowy zostanie utworzony w folderze docelowym, przynajmniej w moim przypadku tak było.
— electroid

Działa to dla mnie świetnie (z końcowym ukośnikiem w folderach). Dziękuję Ci!
— Leopoldo Sanczyk

5
for dir in images2/*; do mv "$dir"/* "images/$(basename "$dir")"; done

Zapętlaj całą zawartość images2korzystania z rozszerzonego globu (aby uniknąć problemów z parsowaniem ls), a następnie mvzawartość tych elementów do pasującego wpisu w images. Używa basenamedo usuwania wiodącej images2ścieżki z globbed ścieżki.


dodaj więcej szczegółów na temat tego, co robi twoje polecenie, aby był użyteczny również dla przyszłych czytelników :)
— Ramesh

1

@ inulinux12, możesz użyć następującej forpętli jednej linii z wiersza poleceń:

$ for dir in images2/*; do mv "$dir"/* "${dir/2/}"; done

Spowoduje to przeniesienie wszystkich plików z images2do imagesodpowiednich katalogów. Uwaga: zakłada się, że żadne pliki nie mają takiej samej nazwy.

Na przykład:

Przed wykonaniem:

$ ls -R images*
images:
ad  adfoo  fe
images/ad:
jpg.1  jpg.2
images/adfoo:
jpg.7
images/fe:
jpg.5
images2:
ad  adfoo  fe
images2/ad:
jpg.3
images2/adfoo:
jpg.6
images2/fe:
jpg.4

Po wykonaniu:

$ ls -R images*
images:
ad  adfoo  fe
images/ad:
jpg.1  jpg.2  jpg.3
images/adfoo:
jpg.6  jpg.7
images/fe:
jpg.4  jpg.5

3
Nie analizuj wyniku ls. mywiki.wooledge.org/ParsingLs
— Etan Reisner

@EtanReisner Dziękuję za sugestię; wydaje się dość wąskie scenariusze, biorąc pod uwagę informacje podane w pytaniu.
— Simply_Me

2
@Simply_Me Chociaż to prawda, że ​​zwykle będzie dobrze, naprawdę nie chcesz, aby wybuchła, gdy trafisz na przypadek, na który nie liczyłeś. Może powodować naprawdę złe problemy. Nie wspominając już o tym, że jest to dość często (jak w tym przypadku) prawie trywialnie zastępowalne prostym globem. Zobacz moją odpowiedź jako przykład tego.
— Etan Reisner,

@Simply_Me Scenariusze zawierają nazwy plików ze spacjami, co jest dość powszechne w przypadku obrazów.
— Gilles

@Gilles i @Etan Reisner, dziękuję za wkład, doceniam to! Zaktualizowałem i przetestowałem moją odpowiedź, aby użyć podstawiania ciągów, i stało się to szybsze niż użycie basenamew tej konkretnej sytuacji (nie trzeba do tego dzwonić basename). Jeszcze raz dziękuję za konstruktywne komentarze.
— Simply_Me,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.