Kopiowanie dużej liczby plików z jednego katalogu do drugiego w systemie Linux

11

Mam katalog zawierający około 280 000 plików. Chcę przenieść je do innego katalogu.

Jeśli użyję cplub mvdostanę błąd, „lista argumentów jest za długa”.

Jeśli napiszę skrypt

for file in ls *; do
   cp {source} to {destination} 
done

następnie, z powodu lspolecenia, jego wydajność spada.

Jak mogę to zrobić?

potrójny
źródło
1
Jaki jest całkowity rozmiar wszystkich plików? Może najpierw tarte pliki?
Zobacz to pytanie .
Nick Presta

Odpowiedzi:

19

Użyj rsync :

$ rsync -a {source}/ {destination}/

na przykład

$ rsync -a /some/path/to/src/ /other/path/to/dest/

(zwróć uwagę na końcowe)


Uwaga: jeśli jest to długa operacja i chcesz zobaczyć pewne informacje o postępie podczas kopiowania, możesz dodać -vopcję (verbose), która następnie wyświetla listę wszystkich kopiowanych plików, lub rozważyć użycie tej --progressopcji, aby uzyskać bardziej zwięzły wynik.

Paul R.
źródło
bash: / usr / bin / rsync: Zbyt długa lista argumentów Przepraszamy Paul !!!!!
@Ritesh - Zgaduję, że podałeś jakieś pliki lub * jako część {source} - powinien to być po prostu katalog, np. rsync -a /some/path/src/ /other/path/to/- zwróć uwagę na końcowe / s.
Tak, Paul. Podałem ścieżkę do katalogu. ale to nie zadziałało!
@Ritesh - to nie wydaje się możliwe - czy możesz skopiować i wkleić aktualną komendę rsync i wynikające z niej komunikaty o błędach z terminala?
Paul R
rsync czasami zgłasza „Lista argumentów za długa”, gdy faktycznym problemem jest zbyt mało wolnego miejsca na dysku docelowym.
jk7,
9

W odpowiedziach brakuje mi dwóch wahań, więc dodaję jeszcze jeden.

Chociaż przypomina mi to dodanie kolejnej standardowej odpowiedzi ...

wprowadź opis zdjęcia tutaj

Istnieją tutaj dwa problemy:

Mam katalog zawierający około 280 000 plików.

Większość narzędzi nie skaluje się tak dobrze przy tej liczbie plików. Nie tylko większość narzędzi Linuksa lub Windows, ale sporo programów. I może to obejmować twój system plików. Długoterminowym rozwiązaniem byłoby „dobrze, nie rób tego wtedy”. Jeśli masz różne pliki, ale w różnych katalogach. Jeśli nie, możesz spodziewać się kolejnych problemów.

Powiedziawszy to, przejdźmy do rzeczywistego problemu:

Jeśli użyję cp lub mv, pojawia się błąd „lista argumentów jest za długa”

Jest to spowodowane rozszerzeniem * przez powłokę. Powłoka ma ograniczone miejsce na wynik i kończy się. Oznacza to, że każde polecenie z *rozszerzeniem przez powłokę napotka ten sam problem. Będziesz musiał albo rozwinąć mniej opcji w tym samym czasie, albo użyć innego polecenia.

Jednym z nich jest często używane alternatywne polecenie find. Jest już kilka odpowiedzi pokazujących, jak z niego korzystać, więc nie zamierzam tego wszystkiego powtarzać. Zwrócę jednak uwagę na różnicę między, \;a +ponieważ może to mieć ogromną różnicę w wydajności i ładnie przyłączyć się do poprzedniego wyjaśnienia dotyczącego rozszerzenia.

find /path/to/search --name "*.txt" -exec command {} \;

Znajduje wszystkie pliki w ścieżce / to / search / i wykonuje z nim polecenie, ale zwraca uwagę na cudzysłów wokół *. To podaje * do polecenia. Gdybyśmy go nie zamknęli ani nie uciekli, powłoka spróbowałaby go rozwinąć i otrzymalibyśmy ten sam błąd.

Na koniec chcę wspomnieć o {}. Te nawiasy zastępowane są treścią znalezioną przez find. Jeśli zakończysz polecenie średnikiem ;(takim, który musisz uciec z powłoki, stąd \;w przykładach), wówczas wyniki są przekazywane jeden po drugim. Oznacza to, że wykonasz komendy 280000 mv. Jeden na każdy plik. To może być powolne.

Alternatywnie możesz zakończyć +. To przekaże jak najwięcej argumentów jednocześnie. Jeśli bash może obsłużyć 2000 argumentów, to find / path -name "* filetype" -exec some_move {} + wywoła komendę some_move około 140 razy, za każdym razem z 2000 argumentami. To jest bardziej wydajne (czytaj: szybciej).

Hennes
źródło
1

Nie potrzebujesz ls, możesz po prostu użyć

for file in *; do
    cp $file /your/dest
done

lub możesz zrobić coś takiego:

echo * | xargs -i cp {} /your/dest
który
źródło
Pierwsze rozwiązanie nie będzie działać, ponieważ problem z wydajnością powinienem wypróbować drugi. Ale po pewnym czasie. Dzięki.
Pierwsze rozwiązanie również dla mnie nie działało. Ten jest jedynym, który działał.
Whitecat,
Pierwsze rozwiązanie nie ma odpowiedniego cytatu, ale poza tym powinno działać i być lepsze niż drugie. Właściwe cytowanie oznacza podwójne cudzysłowy wokół "$file"pętli.
tripleee
0
#!/bin/bash
d=$(date +%Y%m%d%H%m%s)
cd /path
tar zcvf "/destination/bakup_${d}.tar.gz" mydirectory_for_transer
użytkownik31894
źródło
Myślę, że powinienem to zrobić. Ale jedno pytanie wciąż mi chodzi w głowie i jest to wydajność?
1
nie mam miliona plików do przetestowania, więc nie mogę odpowiedzieć na pytanie dotyczące wydajności. musisz przetestować się na serwerze programistycznym.
user31894,
0

Zakładając, że chcesz przenieść pliki w tym samym systemie plików, możesz po prostu zmienić nazwę katalogu zawierającego twoje LACS i gotowe.

Tobu
źródło
0

Lubię rsyncto lub:

find dir1 -type f -exec cp {} dir2 \;
Gafel
źródło
0

Co powiesz na przenoszenie (zamiast kopiowania):

$ find {origin}/ -maxdepth 1 -name "*" -o -name ".*" -exec mv '{}'  {destination}/ ';'

Myślę, że to się zmieni, zachowując strukturę (podkatalogi) i ukryte pliki lub katalogi, a także nie zajmując dodatkowego miejsca, jak w przypadku rsync + rm. A jeśli {origin} i {destination} są na tej samej partycji, będzie szybciej.

jaimealsilva
źródło
0

Używanie tar:

(cd {origin}; tar cf - .)|(cd {destination}; tar xvf -)

Działa, aby zacząć wszystko, gdy początkowo początkowo jest za duże dla rsync, ale delta nie są.

James McGill
źródło
0

W moim przypadku, zarówno cpi rsyncbyły zbyt powolne kopiowanie około 4 milionów plików z HDD na SSD, więc oto jak poszedłem o tym (wszystkie moje pliki były .txt pliki w tym samym folderze, więc dostosować finddo potrzeb klienta):

cd /path/to/source/folder
find . -name '*.txt' -print >/tmp/test.manifest
tar -c -T /tmp/test.manifest | (cd /path/to/destination/folder; tar xfp -)

Musiałem wydrukować nazwy plików do pliku tymczasowego, ponieważ trafiłem w Argument list too longbłąd. Używając tarznacznie poprawionych moich prędkości przesyłania, chociaż mogę założyć, że pliki, które są trudniej skompresowane, mogą nie działać tak dobrze.

Kelly
źródło