Mam dwa dyski z tymi samymi plikami, ale struktura katalogów jest zupełnie inna.
Czy jest jakiś sposób na „przeniesienie” wszystkich plików po stronie docelowej, aby pasowały do struktury strony źródłowej? Może ze skryptem?
Na przykład dysk A ma:
/foo/bar/123.txt
/foo/bar/234.txt
/foo/bar/dir/567.txt
Podczas gdy dysk B ma:
/some/other/path/123.txt
/bar/doo2/wow/234.txt
/bar/doo/567.txt
Pliki, o których mowa, są ogromne (800 GB), więc nie chcę ich ponownie kopiować; Chcę tylko zsynchronizować strukturę, tworząc niezbędne katalogi i przenosząc pliki.
Myślałem o skrypcie rekurencyjnym, który znalazłby każdy plik źródłowy w miejscu docelowym, a następnie przeniósł go do odpowiedniego katalogu, tworząc go w razie potrzeby. Ale - to przekracza moje możliwości!
Inne eleganckie rozwiązanie podano tutaj: /superuser/237387/any-way-to-sync-directory-structure-when-the-files-are-already-on-both-sides/238086
Odpowiedzi:
Pójdę z Gillesem i wskażę ci Unisona, jak sugeruje hasen j . Unison był DropBox 20 lat przed DropBox. Twardy, solidny kod, z którego korzysta wiele osób (w tym ja) każdego dnia - warto się tego nauczyć. Mimo to
join
potrzebuje całej reklamy, jaką może uzyskać :)To tylko połowa odpowiedzi, ale muszę wrócić do pracy :)
Zasadniczo chciałem zademonstrować mało znane
join
narzędzie, które właśnie to robi: łączy dwie tabele na pewnym polu.Najpierw skonfiguruj przypadek testowy zawierający nazwy plików ze spacjami:
(edytuj niektóre nazwy katalogów i / lub plików w
new
).Teraz chcemy zbudować mapę: skrót -> nazwa pliku dla każdego katalogu, a następnie użyć
join
do dopasowania plików z tym samym skrótem. Aby wygenerować mapę, wpiszmakemap.sh
:makemap.sh
wyrzuca plik z wierszami formularza „hash” nazwa pliku ”, więc dołączamy tylko do pierwszej kolumny:Generuje to,
moves.txt
które wygląda następująco:Następnym krokiem byłoby wykonanie ruchów, ale moje próby utknęły w miejscu ...
mv -i
imkdir -p
powinny się przydać.źródło
join
jest naprawdę interesujące. Dziękuję za zwrócenie mi na to uwagi.join
dane wejściowe?Istnieje narzędzie o nazwie unison:
http://www.cis.upenn.edu/~bcpierce/unison/
Opis ze strony:
Pamiętaj, że Unison wykrywa przeniesione pliki przy pierwszym uruchomieniu tylko wtedy, gdy przynajmniej jeden z katalogów głównych jest zdalny, więc nawet jeśli synchronizujesz pliki lokalne, użyj go
ssh://localhost/path/to/dir
jako jednego z katalogów głównych.źródło
Użyj Unison zgodnie z sugestią hasen j . Pozostawiam tę odpowiedź jako potencjalnie przydatny przykład skryptowy lub do użytku na serwerze z zainstalowanymi tylko podstawowymi narzędziami.
Zakładam, że nazwy plików są unikalne w całej hierarchii. Zakładam również, że żadna nazwa pliku nie zawiera nowego wiersza, a drzewa katalogów zawierają tylko katalogi i zwykłe pliki.
Najpierw zbierz nazwy plików po stronie źródłowej.
Następnie przenieś pliki na miejsce po stronie docelowej. Najpierw utwórz spłaszczone drzewo plików po stronie docelowej. Użyj
ln
zamiast,mv
jeśli chcesz zachować twarde linki w starej hierarchii.Jeśli brakuje niektórych plików w miejscu docelowym, utwórz podobnie spłaszczony
/A.staging
i użyj rsync, aby skopiować dane ze źródła do miejsca docelowego.Teraz zmień nazwę plików na swoje miejsce.
Równoważnie:
Na koniec, jeśli zależy ci na metadanych katalogów, wywołaj rsync z plikami, które już istnieją.
Pamiętaj, że nie testowałem fragmentów w tym poście. Używaj na własne ryzyko. Zgłoś każdy błąd w komentarzu.
źródło
Szczególnie, jeśli przydałaby się ciągła synchronizacja, możesz spróbować znaleźć załącznik git .
Jest stosunkowo nowy; Sam nie próbowałem tego użyć.
Mogę to zasugerować, ponieważ unika się przechowywania drugiej kopii plików ... oznacza to, że musi oznaczać pliki jako tylko do odczytu („zablokowane”), podobnie jak niektóre systemy kontroli wersji inne niż Git.
Pliki są identyfikowane przez rozszerzenie pliku sha256sum + (domyślnie). Powinien więc być w stanie zsynchronizować dwa repozytoria z identyczną zawartością pliku, ale różnymi nazwami plików, bez konieczności wykonywania operacji zapisu (i w razie potrzeby w sieci o niskiej przepustowości). Będzie oczywiście musiał przeczytać wszystkie pliki, aby je zsumować.
źródło
Co powiesz na coś takiego:
Zakłada się, że nazwy plików, które chcesz zsynchronizować, są unikalne na całym dysku: w przeciwnym razie nie będzie możliwości pełnej automatyzacji (możesz jednak poprosić użytkownika o wybranie pliku do wyboru, jeśli jest więcej.)
Powyższy skrypt będzie działał w prostych przypadkach, ale może się nie powieść, jeśli
name
zawiera symbole mające specjalne znaczenie dla wyrażeń regularnych.grep
Na liście plików może także zająć dużo czasu, jeśli jest dużo plików. Możesz rozważyć przetłumaczenie tego kodu na hashtable, który mapuje nazwy plików na ścieżki, np. W Ruby.źródło
grep
linia? Czy po prostu znajduje pełną ścieżkę pasującego plikudstlist
?ln
niemu tworzy dowiązania symboliczne. Możesz użyćmv
do przeniesienia plików, ale uważaj na nadpisywanie istniejących. Ponadto możesz usunąć puste katalogi, jeśli takie istnieją, po przeniesieniu plików. Tak, togrep
polecenie wyszukuje wiersz, który kończy się na nazwie pliku, tym samym ujawniając pełną ścieżkę do niego na dysku docelowym.Zakładając, że podstawowe nazwy plików są unikalne w drzewach, jest to dość proste:
Jeśli chcesz wyczyścić stare puste katalogi, użyj:
źródło
Też napotkałem ten problem. Rozwiązanie oparte na md5sum nie działało dla mnie, ponieważ synchronizuję moje pliki z
webdav
montażem. Obliczanie sum md5 na miejscuwebdav
docelowym oznaczałoby również operacje na dużych plikach.Zrobiłem mały skrypt
reorg_Remote_Dir_detect_moves.sh
(na github), który próbuje wykryć najczęściej przenoszone pliki, a następnie tworzy nowy tymczasowy skrypt powłoki z kilkoma poleceniami do dostosowania katalogu zdalnego. Ponieważ dbam tylko o nazwy plików, skrypt nie jest idealnym rozwiązaniem.Ze względów bezpieczeństwa kilka plików zostanie zignorowanych: A) Pliki o takich samych (tych samych początkowych) nazwach po każdej stronie i B) Pliki, które znajdują się tylko po stronie zdalnej. Zostaną zignorowani i pominięci.
Pominięte pliki będą następnie obsługiwane przez preferowane narzędzie synchronizacji (np.
rsync, unison
...), którego musisz użyć po uruchomieniu tymczasowego skryptu powłoki.Więc może mój skrypt jest dla kogoś przydatny? Jeśli tak (aby było bardziej jasne), są trzy kroki:
reorg_Remote_Dir_detect_moves.sh
(na github)/dev/shm/REORGRemoteMoveScript.sh
=> uruchom to, aby wykonać ruchy (będzie szybko montowanewebdav
)rsync, unison
...)źródło
Oto moja próba odpowiedzi. Jako ostrzeżenie, całe moje doświadczenie związane ze skryptami pochodzi od bash, więc jeśli używasz innej powłoki, nazwy poleceń lub składnia mogą być inne.
To rozwiązanie wymaga utworzenia dwóch osobnych skryptów.
Ten pierwszy skrypt odpowiada za przeniesienie plików na dysk docelowy.
Drugi skrypt tworzy plik mapy md5 używany przez pierwszy skrypt, a następnie wywołuje pierwszy skrypt na każdym pliku na dysku docelowym.
Zasadniczo dwa skrypty symulują tablicę asocjacyjną
$md5_map_file
. Po pierwsze, wszystkie pliki md5 dla plików na dysku źródłowym są obliczane i przechowywane. Z md5 związane są ścieżki względne od katalogu głównego dysku. Następnie dla każdego pliku na dysku docelowym obliczane jest md5. Korzystając z tego md5, ścieżka tego pliku na dysku źródłowym jest sprawdzana. Plik na dysku docelowym jest następnie przenoszony zgodnie z ścieżką pliku na dysku źródłowym.Istnieje kilka zastrzeżeń dotyczących tego skryptu:
źródło
md5sum
Wydaje się , że nie należy go tutaj używać. (BTW,rsync
ma tryb, w którym nie oblicza sum kontrolnych.)