Mam miliony zdjęć na moim serwerze w chmurze ubuntu. Kiedy przenoszę cały folder zawierający 12 milionów obrazów za pomocą mv
polecenia, dzieje się to niemal natychmiast. Kiedy jednak mv
tylko obrazy (nie folder) to zajmuje trochę czasu. Czy istnieje sposób na przeniesienie wszystkich obrazów tak szybko, jak foldery?
Oto co się dzieje:
Folder src ma 12 milionów obrazów i przenoszę go do folderu dst za pomocą
$ mv src ../dst
Zdarza się natychmiast
W folderze src robię to, aby przenieść:
find -maxdepth 1 -name '*.jpg' -exec mv -t ../../dst/ {} +
To zajmuje trochę czasu.
Czy istnieje sposób na przyspieszenie drugiego procesu?
dst
jest na partycji, podczas gdy../../dst
na innej.{}
argumentu, w którym nazwa (-y) pliku (-ów) zostałaby rozwinięta.find
.find ... -exec mv -t ../../dst/ {} \;
zadzwoniłbymv
raz na plik;find ... -exec mv -t ../../dest {} +
byłoby znacznie szybsze, kopiowanie jak największej liczby plików na połączenie, ale nadal nie tak szybkie, jak przenoszenie samego katalogu, jak wyjaśniono w dadexix86 .Odpowiedzi:
TL; DR : Nie
W przypadku mniejszej liczby plików nie potrzebujesz,
find
ale nawet w tym uproszczonym i mniejszym przypadku, jeśli tylko chceszzajmie to więcej czasu niż przeniesienie całego katalogu na raz.
Czemu? Chodzi o to, aby zrozumieć, co
mv
robi.Krótko mówiąc,
mv
przenosi liczbę (identyfikującą katalog lub plik) z i-węzła (katalogu zawierającego go) do innego, a te wskaźniki są aktualizowane w dzienniku systemu plików lub w FAT (jeśli system plików jest zaimplementowany w taki sposób).Jeśli źródło i miejsce docelowe znajdują się w tym samym systemie plików, rzeczywisty ruch danych nie występuje, zmienia się tylko pozycja, punkt, do którego są przyłączone.
Tak więc, gdy masz
mv
jeden katalog, wykonujesz tę operację jeden raz .Ale kiedy przenosisz 1 milion plików, wykonujesz tę operację milion razy .
Aby dać ci praktyczny przykład, masz drzewo z wieloma gałęziami. W szczególności istnieje jeden węzeł, do którego przyłączony jest 1 milion oddziałów.
Aby wyciąć te gałęzie i przenieść je gdzie indziej, możesz albo wyciąć każdy z nich, aby wykonać 1 milion cięć, lub wyciąć tuż przed węzłem, w ten sposób wykonując tylko jedno cięcie (jest to różnica między przenoszeniem plików i katalog).
źródło
mv
w tym samym systemie plików jest tylko przepisanie wpisu spisu treści.mv *.jpg
prawdopodobnie zawiedzie dla 12 milionów plików, dlatego używa find. Uważam, że większość uniksów, w tym Linux (chyba, że ktoś to zmienił w ciągu ostatnich 5-10 lat) ma ograniczoną maksymalną długość wiersza poleceń. Myślę, że przez długi czas było to 64 KB dla Linuksa. Ten sam limit dotyczy zmiennych środowiskowych, jestem całkiem pewien.Nadal będzie powolny, ponieważ, jak wspomniano, system plików musi ponownie połączyć każdą nazwę pliku z nową lokalizacją.
Możesz jednak przyspieszyć to, co już masz.
Polecenie find uruchamia exec raz dla każdego pliku. Więc uruchamia
mv
polecenie 12 milionów razy dla 12 milionów plików. Można to poprawić na dwa sposoby.Dodaj plus na końcu:
find -maxdepth 1 -name '*.jpg' -exec mv -t ../../dst/ +
sprawdź stronę podręcznika, aby upewnić się, że jest obsługiwany w twojej wersji
find
. Efektem powinno być uruchomienie seriimv
poleceń z tyloma nazwami plików, ile zmieści się w każdym wierszu poleceń.Użyj
find
ixargs
razem. Użyje NUL, aka zero bajtów, aby oddzielić nazwy plików. To plus naprawia wszelkie problemy, które w innym przypadku występowałyby ze spacjami w nazwach plików. Komenda odczyta listę nazw plików z polecenia i uruchom polecenie na tyle nazw plików, ile się zmieści.find -maxdepth 1 -name '*.jpg' -print0 | xargs -0 mv -t ../../dst/
-print0
xargs -0
xargs
xargs
find
mv
źródło
Twoje zamieszanie wynika z abstrakcji systemu plików, która sprawia, że uważasz, że folder zawiera pliki i inne foldery w stylu drzewiastym. W rzeczywistości nie jest to prawdą: wszystkie pliki i katalogi w systemie plików znajdują się na tym samym poziomie i są identyfikowane liczbami w zależności od implementacji. Katalogi to tylko specjalne pliki zawierające listy innych plików.
Gdy „przenosisz” pliki do systemu plików, rzeczywiste pliki nigdzie nie trafiają. Zamiast tego listy w katalogach są aktualizowane, aby odzwierciedlić zmianę.
mv src ../dst
przenosi pojedynczy wpis listy z katalogu.
do katalogu../dst
, więc jest szybki.find -maxdepth 1 -name '*.jpg' -exec mv -t ../../dst/
musi przenieść miliony wpisów, więc jest wolniejszy. Można to potencjalnie przyspieszyć, jeśli wywołujeszmv
tylko raz, a nie raz na plik, amv
sama komenda może być zoptymalizowana do przenoszenia kilku pozycji katalogu w jednym kroku, ale nie ma sposobu, aby uczynić ją tak szybką, jak przy przenoszeniu jednego katalogu .źródło
Uproszczona odpowiedź
przeniesienie pliku odbywa się w 3 krokach:
ten proces jest taki sam dla pliku lub folderu.
i oczywiście robienie tego dla 1 pliku jest 100 szybsze niż robienie tego dla 100 plików.
man link
jest add ()man unlink
to remove ()mv
używa tylko tych dwóch poleceń powyżej i dodaje między nimi kontrolę, aby zapobiec utracie danych.źródło