Na dysku znajduje się 5 ogromnych plików (plik 1, plik 2, ... plik 5) o wielkości około 10 GB i bardzo mało wolnego miejsca na dysku i muszę połączyć wszystkie te pliki w jeden. Nie ma potrzeby przechowywania oryginalnych plików, tylko ostatni.
Zwykle konkatenacja odbywa się cat
dla plików file2
.. file5
:
cat file2 >> file1 ; rm file2
Niestety ten sposób wymaga co najmniej 10G wolnego miejsca, którego nie mam. Czy istnieje sposób na konkatenację plików bez faktycznego kopiowania, ale powiedzieć systemowi plików, że plik1 nie kończy się na oryginalnym końcu pliku 1 i kontynuuje na początku pliku 2?
ps. system plików to ext4, jeśli to ma znaczenie.
filesystems
files
wysypka
źródło
źródło
nbd-server
.Odpowiedzi:
AFAIK (niestety) nie jest możliwe obcięcie pliku od samego początku (może to dotyczyć standardowych narzędzi, ale dla poziomu syscall patrz tutaj ). Ale dodając pewną złożoność, możesz użyć normalnego obcięcia (razem z rzadkimi plikami): Możesz pisać na końcu pliku docelowego bez zapisywania wszystkich danych pomiędzy nimi.
Załóżmy, że najpierw oba pliki mają dokładnie 5GiB (5120 MiB) i że chcesz przenieść 100 MiB jednocześnie. Wykonujesz pętlę, która składa się z
obcięcie pliku źródłowego o jeden blok (zwolnienie miejsca na dysku)
Ale spróbuj najpierw z mniejszymi plikami testowymi, proszę ...
Prawdopodobnie pliki nie mają tego samego rozmiaru ani wielokrotności rozmiaru bloku. W takim przypadku obliczenia przesunięć stają się bardziej skomplikowane.
seek_bytes
iskip_bytes
należy z tego skorzystać.Jeśli tak chcesz, ale potrzebujesz pomocy w zakresie szczegółów, zapytaj ponownie.
Ostrzeżenie
W zależności od
dd
rozmiaru bloku wynikowy plik będzie koszmarem fragmentacji.źródło
Zamiast łączyć pliki razem w jeden plik, może symulować pojedynczy plik z nazwanym potokiem, jeśli twój program nie obsługuje wielu plików.
Jak sugeruje Hauke, losetup / dmsetup może również działać. Szybki eksperyment; Stworzyłem „plik1..plik4” i przy odrobinie wysiłku:
Następnie / dev / dm-0 zawiera wirtualne urządzenie blokowe z plikiem jako zawartością.
Nie przetestowałem tego dobrze.
Kolejna edycja: rozmiar pliku musi być podzielny równomiernie przez 512, inaczej stracisz trochę danych. Jeśli tak, to jesteś dobry. Widzę, że zauważył to również poniżej.
źródło
dmsetup
z wirtualnym urządzeniem blokowym (co pozwala na normalne operacje wyszukiwania, ale nie dołącza ani nie obcinają). Jeśli rozmiar pierwszego pliku nie jest wielokrotnością 512, należy skopiować niekompletny ostatni sektor i pierwsze bajty z drugiego pliku (łącznie 512) do trzeciego pliku. Potrzebne byłoby--offset
wówczas urządzenie pętli dla drugiego pliku .Musisz napisać coś, co kopiuje dane w pęczkach, które są co najwyżej tak duże, jak ilość wolnego miejsca. Powinno działać tak:
file2
(używającpread()
, szukając przed odczytem do właściwej lokalizacji).file1
.fcntl(F_FREESP)
aby zwolnić miejscefile2
.źródło
fcntl(F_FREESP)
czemu zwalnia miejsce związane z danym zakresem bajtów pliku (czyni go rzadkim).fcntl
stronie podręcznika (15.04.2012).fallocate
syscall. Nowsze wersje narzędzia fallocateutil-linux
mają interfejs do tego.Wiem, że jest to bardziej obejście niż to, o co prosiłeś, ale rozwiązałoby problem (z niewielką fragmentacją lub zarysowaniem):
i wtedy
lub jeśli uważasz, że kompresja pomogłaby:
W końcu (i TYLKO wtedy)
źródło