Najlepsza praktyka, aby kontynuować mv

13

Użyłem terminala do skopiowania plików z jednego dysku na drugi.

sudo mv -vi /location/to/drive1/ /location/to/drive2/

Jednak nagle przestało, po kilku godzinach i bez błędu, po utworzeniu katalogu.

Moje własne rozwiązanie tego problemu jest często mieszaniem haszowania i porównywania, co jest w większości czasochłonnym bałaganem, ponieważ teraz muszę odzyskać kopię pośrednią, nie bardzo wiedząc, które pliki brakuje (napisane jako bardzo długi jednowarstwowy dla zsh - pamiętaj, że ten skrypt nie działa w bashu jak napisano):

source_directory="/path/to/source_directory/";
target_directory="/path/to/target_directory/";
while read hash_and_file; do {
    echo "${hash_and_file}" | read hash file;
    echo "${file}" | sed "s/^/${source_directory}/g" | read copy_from;
    echo "${copy_from}" | sed "s/${source_directory}/${target_directory}/g" | read copy_to;
    mv -v "${copy_from}" "${copy_to}" | tee -a log;
    rm -v "${copy_from}" | tee -a log; };
done <<<$(
    comm -23 <( find ${source_directory} -type f -exec sha256sum "{}" \; |
                sed "s: ${source_directory}: :g" | sort;
           ) <( find ${target_directory} -type f -exec sha256sum "{}" \; |
                sed "s: ${target_directory}: :g" | sort; ) )

Jest to podatne na błędy, jeśli katalog docelowy nazwy lub katalog_źródłowy są częścią ścieżki i usuwają pliki, jeśli nie zostały przeniesione, ponieważ zostały oznaczone jako duplikaty. Poza tym na końcu nie zawiera katalogu źródłowego.

Czy istnieje najlepsza praktyka odzyskiwania po przerwie w MV?

Co
źródło
Napisałem podobny skrypt , który używa cmpzamiast mieszania. Ma zależności i te same problemy, o while readktórych wspomniał Gilles. Jest również powolny i pełny. Ale zwalnia miejsce na dysku wcześniej niż metoda rsync, ponieważ pliki są (ponownie) przenoszone ze źródła podczas działania. Może służyć jako inspiracja dla odważnych.
joeytwiddle
3
@joeytwiddle rsync oferty --delete-during receiver deletes during the transfer, a także kilka innych przydatnych możliwości: --delete --delete-before --delete-delay --delete-after --delete-excluded. Więc tak, rsync jest najlepszą alternatywą,
NotAnUnixNazi
Coś mi brakuje. Dlaczego powtarzanie tego samego mvpolecenia nie działa? Być może z *dołączoną do ścieżki źródłowej, jeśli oryginalnym źródłem był katalog.
jpa
@isaac Nie, obawiam się, rsync --delete*że to będzie katastrofa ! To usunie rzeczy, z destktórych obecnie nie ma src, więc wszystkie pliki, które zostały pomyślnie przeniesione w poprzedniej próbie, zostaną teraz usunięte! Prawdopodobnie myślałeś, rsync --remove-source-filesże zgadzam się, że byłaby dobrą alternatywą. ( more1 , more2 )
joeytwiddle
@joeytwiddle Nie, rsync --deletebędzie tylko usunąć inne pliki, które nie są częścią źródła. Z [man rsync] () * usuń niepotrzebne pliki z dest dirs *. Zrozum, co znaczy obce : brak synchronizacji. I tak, rsync również zapewnia sposób, aby usunąć pliki źródłowe po ich poprawnie wysłany.
NotAnUnixNazi

Odpowiedzi:

46

Zapomnij o ponownym wymyśleniu rsync i użyj rsync.

sudo rsync -av /location/to/drive1/ /location/to/drive2/

Upewnij się, że używasz końcowego ukośnika na źródle, w przeciwnym razie zostanie skopiowany /location/to/drive2/drive1.

Sprawdź dwukrotnie, czy polecenie się powiodło, a następnie uruchom rm -rf /location/to/drive1/.

Powyższe polecenie zastąpi każdy istniejący plik drive2. Jeśli chcesz poprosić użytkownika o pominięcie plików, które już istniały drive2, tak jak w przypadku mv -i, jest to bardziej skomplikowane, ponieważ musisz teraz odróżnić pliki, które zostały już skopiowane, i pliki, które nie zostały. Możesz przekazać --ignore-existingopcję rsync, aby pominąć pliki, które już istnieją w miejscu docelowym, niezależnie od ich zawartości. Zwróć uwagę, że jeśli oryginał mvzostał przerwany w trakcie tworzenia pliku, plik ten pozostanie w stanie w połowie skopiowanym (podczas gdy rsync -akopia go poprawnie zakończy kopiowanie).

Jeśli chcesz odtworzyć dokładne zachowanie mv -i, w tym monitowanie, można to zrobić, ale jest to o wiele bardziej skomplikowane.

Pamiętaj, że twój jeden gigantyczny liniowiec jest bardzo delikatny. Jeśli istnieją nazwy plików zawierające odwrotne ukośniki lub znaki nowej linii, mogą nie zostać poprawnie skopiowane lub mogą nawet oszukać skrypt do usunięcia dowolnych plików. Więc nie używaj kodu w pytaniu , chyba że jesteś pewien, że można zaufać nazwy plików nie zawierają backslashy lub znakami nowej linii.

Na przyszłość zalecam, aby nigdy nie używać mvdo dużych ruchów na krzyż, właśnie dlatego, że trudno jest kontrolować, co się stanie, jeśli zostanie przerwane. Użyj rsync, aby wykonać kopiowanie, a następnie usuń oryginał.

Gilles „SO- przestań być zły”
źródło
Jakie obietnice daje rsync, że mv nie robi?
Co
4
na przykład rsyncrobi to, co próbujesz zrobić, a mvnie robi. Ponadto: kopiowanie między różnymi komputerami; kompresja do transferu; pomijanie plików istniejących w miejscu docelowym na podstawie równości opartej na znacznikach czasu lub hash; konfigurowalna obsługa własności, uprawnień, łączy i plików specjalnych; itp. linux.die.net/man/1/rsync
Silly Freak
1
@ SillyFreak powinienem wyciągnąć z tego wniosek, że zawsze powinienem używać rsync zamiast mv, nie tylko jak powiedział Gilles dla cross-drive, ale każda operacja, ponieważ granica „zbyt dużej” jest względnie subiektywna i jeśli chodzi o problem i tak zostałby rozwiązany przez rsync?
Co
9
cóż, kiedy przenoszę pliki lub katalogi na jednej partycji, zwykle używam mv(lub menedżera plików), ponieważ przenosi tylko odwołanie do pliku / katalogu. Jeśli muszę dokonać faktycznego transferu danych, używam, rsyncjeśli spełniony jest jeden z poniższych warunków: 1) Przenoszę więcej plików, niż mogę sprawdzić na pierwszy rzut oka, czy przesyłanie jest prawidłowe; 2) Przewiduję, że będę musiał synchronizować pliki; 3) Spodziewam się, że transfer może zostać przerwany. Chodzi mi o to, w przypadku użycia jesteś prezentując w pytaniu, rsyncjest po prostu właściwym narzędziem, i mvczy cpnie są.
Silly Freak,
7
Radziłbym zawsze uruchamiać dowolną komendę rsync z opcją -v i - najpierw uruchom na sucho, aby potwierdzić dokładnie, co zamierza zrobić.
Darren,