Jaki jest najlepszy sposób na ponowne dołączenie plików po ich podzieleniu?

73

Jeśli mam duży plik i muszę go podzielić na 100 megabajtów, zrobię to

split -b 100m myImage.iso

To zwykle daje mi coś takiego

xaa
xab
xac
xad

I żeby je z powrotem połączyć, używałem

cat x* > myImage.iso

Wydaje się, że powinien istnieć bardziej wydajny sposób niż czytanie każdego wiersza kodu w grupie plików cati przekierowywanie danych wyjściowych do nowego pliku. Jak sposób na otwarcie dwóch plików, usunięcie EOFznacznika z pierwszego i połączenie ich - bez konieczności przeglądania całej zawartości.

Windows / DOS ma polecenie kopiowania plików binarnych. Pomoc wspomina, że ​​to polecenie zostało zaprojektowane tak, aby móc łączyć wiele plików. Działa z tą składnią: ( /bdotyczy trybu binarnego)

copy /b file1 + file2 + file3 outputfile

Czy istnieje coś podobnego lub lepszy sposób łączenia dużych plików w systemie Linux niż cat?

Aktualizacja

Wygląda na catto, że jest to właściwy sposób i najlepszy sposób łączenia plików. Cieszę się, że przez cały czas używałem właściwego polecenia :) Dziękujemy wszystkim za opinie.

cwd
źródło
22
Uwaga dodatkowa: Lepiej nie używać cat x*, ponieważ kolejność plików zależy od ustawień regionalnych. Lepiej zacznij pisać cat x, niż naciśnij Esc, a następnie *- zobaczysz rozszerzoną kolejność plików i możesz zmienić kolejność.
rozcietrzewiacz
16
Zamiast tego cat x*możesz rozważyć rozszerzenie nawiasów klamrowych, cat xa{a..g}które rozszerza określoną sekwencję do cat xaa xab xac xad xae xaf xag
Peter.O
3
@rozcietrzewiacz - czy możesz podać przykład, w jaki sposób dostosowałbym ustawienia regionalne, które by się zepsuły cat x*? Czy nowe ustawienie regionalne nie wpływa również splittak, że jeśli spliti cat x*były używane w tym samym systemie będą zawsze działa?
cwd 15.11. O
3
„otwieranie dwóch plików, usuwanie znacznika EOF z pierwszego i łączenie ich - bez konieczności przeglądania całej zawartości.” ... brzmi jak wymyślenie nowego systemu plików, aby robić to, co chcesz
JoelFan
6
@cwd: Patrząc split.cw GNU Coreutils, przyrostki są zbudowane ze stałej tablicy znaków: static char const *suffix_alphabet = "abcdefghijklmnopqrstuvwxyz";. Ustawienia regionalne nie będą miały wpływu na przyrostek. (Ale nie sądzę, że jakikolwiek rozsądny lokalny porządek zmieniłby małe litery; nawet EBCDIC zachowuje ich standardową kolejność.)
Keith Thompson

Odpowiedzi:

50

Właśnie po to catzostał stworzony. Ponieważ jest to jedno z najstarszych narzędzi GNU, myślę, że jest mało prawdopodobne, aby jakiekolwiek inne narzędzie działało tak szybciej / lepiej. I to nie jest potokowanie - to tylko przekierowanie wyjścia.

rozcietrzewiacz
źródło
cat x, then press EscTrik wspomniałeś jest schludny .. Szukałem czegoś takiego, dzięki ... dobry komentarz i dobra odpowiedź
Peter.O
2
Nie ma za co :) Również, gdy masz listę plików w wierszu poleceń, możesz Ctrl+Wwyciąć słowo, a następnie Ctrl+Ywkleić je.
rozcietrzewiacz
kot oznacza „konkatenat”
JoelFan
4
.. a „catenate” wywodzi się z łacińskiego słowa „catena”, co oznacza „łańcuch” .. łączenie łączy łańcuch. ... (i nieco nie na temat, krzywa sieci trakcyjnej również wywodzi się z „catena”. W ten sposób zawiesza się łańcuch)
Peter.O
19

Pod maską

Nie ma bardziej wydajnego sposobu niż skopiowanie pierwszego pliku, a następnie skopiowanie drugiego pliku po nim i tak dalej. Zarówno DOS, jak copyi catzrób to.

Każdy plik jest przechowywany niezależnie od innych plików na dysku. Prawie każdy system plików zaprojektowany do przechowywania danych na urządzeniu podobnym do dysku działa blokowo. Oto bardzo uproszczona prezentacja tego, co się dzieje: dysk jest podzielony na bloki, powiedzmy 1kB, a dla każdego pliku system operacyjny przechowuje listę bloków, które go tworzą. Większość plików nie ma całkowitej liczby bloków, więc ostatni blok jest tylko częściowo zajęty. W praktyce systemy plików mają wiele optymalizacji, takich jak współdzielenie ostatniego częściowego bloku między kilkoma plikami lub przechowywanie „bloków 46798 do 47913” zamiast „bloku 46798, bloku 46799,…”. Gdy system operacyjny musi utworzyć nowy plik, szuka wolnych bloków. Bloki nie muszą być następujące po sobie: jeśli tylko bloki 4, 5, 98 i 178 są wolne, nadal możesz przechowywać plik 4kB.

Możesz obsługiwać częściowe bloki w środkowym pliku, ale zwiększyłoby to złożoność, szczególnie w przypadku niesekwencyjnego uzyskiwania dostępu do plików: aby przejść do 10340 bajtu, nie można już przeskoczyć do 100 bajtu 11 bloku, musisz mieć aby sprawdzić długość każdego interweniującego bloku.

Biorąc pod uwagę użycie bloków, nie można po prostu połączyć dwóch plików, ponieważ ogólnie pierwszy plik kończy się w połowie bloku. Jasne, możesz mieć specjalny przypadek, ale tylko wtedy, gdy chcesz usunąć oba pliki podczas konkatenacji. Byłoby to bardzo specyficzne postępowanie w przypadku rzadkich operacji. Taka specjalna obsługa nie działa sama, ponieważ w typowym systemie plików dostęp do wielu plików jest uzyskiwany jednocześnie. Więc jeśli chcesz dodać optymalizację, musisz dokładnie przemyśleć: co się stanie, jeśli jakiś inny proces odczyta jeden z zaangażowanych plików? Co się stanie, jeśli ktoś spróbuje połączyć A i B, gdy ktoś będzie konkatenował A i C? I tak dalej. Podsumowując, ta rzadka optymalizacja byłaby ogromnym obciążeniem.

Podsumowując, nie można uczynić łączenia plików bardziej wydajnymi bez większych poświęceń gdzie indziej. To nie jest tego warte.

Na podział i łączenie

spliti catsą prostymi sposobami dzielenia i łączenia plików. splitzajmuje się tworzeniem plików o nazwach uporządkowanych alfabetycznie, dzięki czemu cat *działa przy łączeniu.

Minusem catłączenia jest to, że nie jest odporny na typowe tryby awarii. Jeśli jeden z plików jest obcięty lub brakuje go, catnie będzie narzekać, po prostu otrzymasz uszkodzony wynik.

Istnieją narzędzia do kompresji, które tworzą archiwa wieloczęściowe, takie jak zipspliti rar -v. Nie są one bardzo uniksowe, ponieważ kompresują i pakują (składają wiele plików w jeden) oprócz dzielenia (i odwrotnie rozpakowują i dekompresują oprócz łączenia). Ale są przydatne, ponieważ sprawdzają, czy masz wszystkie części i że części są kompletne.

Gilles
źródło
8

Wydaje się, że powinien istnieć bardziej wydajny sposób niż przesyłanie całej zawartości przez system stdin/stdout

Tyle że tak naprawdę to się nie dzieje. Powłoka łączy stdout cat bezpośrednio z otwartym plikiem, co oznacza, że ​​„przejście przez stdout” jest tym samym, co zapis na dysk.

Ignacio Vazquez-Abrams
źródło
Właśnie sobie wyobrażałem użycie cat do wyświetlenia kilku gigabajtów kodu w konsoli, a następnie przechwycenie go i umieszczenie w pliku. Taki jest mentalny obraz tego, co musi się dziać, kiedy używam cat i przekierowuję wyjście, którego nie widzę. Wydawało się, że gdyby istniał sposób, aby otworzyć dwa pliki, połączyć je, a następnie zamknąć, byłoby to bardziej wydajne niż uruchomienie wszystkich linii kodu za pomocą cat. Dziękujemy za poinformowanie mnie o bezpośrednim połączeniu.
cwd 15.11. O
@cwd Możliwe byłoby zaprojektowanie systemu plików, w którym można by w ten sposób połączyć dwa pliki, ale to ogromnie skomplikowałoby projektowanie systemu plików. Zoptymalizowałbyś tę jedną operację kosztem uczynienia wielu typowych zadań bardziej skomplikowanymi i wolniejszymi.
Gilles
@Gilles - warto dowiedzieć się więcej o szczegółach niskiego poziomu. Dla mnie odczytanie wszystkich sektorów z dysku twardego dla kilku plików, a następnie zrzucenie ich z powrotem do innych nieużywanych sektorów na dysku wydaje się nieefektywne. I myślę, że duże pliki muszą być przechowywane w wielu blokach wolnych sektorów, ponieważ nie zawsze może być wystarczająca ilość bloków obok siebie, aby je przechowywać. Dlatego teoretycznie można połączyć pliki w jeden, usuwając znacznik EOF i wskazując grupę sektorów na początku następnego pliku. * Nix jest potężny, więc zastanawiałem się, czy istnieje lepszy sposób niż kot.
cwd 15.11. O
@cwd Nie ma „znacznika EOF”. Żaden rozsądny nowoczesny system plików nie działa w ten sposób, ponieważ zapobiega występowaniu niektórych znaków w plikach (lub wymaga skomplikowanego kodowania). Ale nawet jeśli byłby znacznik EOF, przez większość czasu nie miałbyś po nim odpowiedniego pliku.
Gilles
Miałem na myśli koncepcję markera EOF, a nie rzeczywisty marker EOF. W przeciwnym razie, jeśli spojrzysz na bity i bajty pliku na dysku twardym, skąd wiesz, gdzie się on kończy? Czy określasz długość pliku na początku? Mówię o rzeczy naprawdę niskiego poziomu. Czy to też masz na myśli?
cwd 16.11.11
3

Kiedyś miałem dokładnie ten problem: chciałem dołączyć do niektórych plików, ale nie miałem wystarczająco dużo miejsca na dysku, aby pomieścić je podwójnie.

Napisałem więc kilka programów:

  • jeden, aby „zassać” plik, czytając go, wysyłając na standardowe wyjście, a jeśli skończysz, usuwamy go
  • i jeden do buforowania danych „w locie”.

To pozwoliło mi zrobić coś takiego

partto sourcefile | mybuffer 128M >>cumufile

i tym samym usuwając plik źródłowy, gdy 128M był jeszcze niepisany. Trochę niebezpieczne, ale jeśli dane nie są tak cenne lub istnieją również gdzie indziej, jest to wykonalne.

W razie potrzeby mogę podać źródło.

glglgl
źródło
0

Technicznie rzecz biorąc, jest to sposób na uzyskanie dostępu do całego pliku bez konieczności odczytywania i zapisywania całej zawartości, i może być przydatny w przypadku dużych plików lub jeśli pozostało mało miejsca:

$ mkfifo myImage.iso
$ cat xa{a..g} > myImage.iso &

A następnie użyj myImage.isona przykład

$ md5sum myImage.iso

Chociaż oczywiście myImage.isojest to specjalny plik (nazwany potok), a nie zwykły plik, więc może się przydać lub nie, w zależności od tego, co próbujesz zrobić.

Golimar
źródło
0

Podział plików

Podziel według rozmiaru

Jeśli chcesz podzielić duży plik na małe pliki i wybrać nazwę i rozmiar małych plików wyjściowych, tak właśnie jest.

split -b 500M videos\BigVideoFile.avi SmallFile.

W ten sposób decydujesz się podzielić jeden duży plik na mniejsze części o pojemności 500 MB. Chcesz również, aby nazwy plików części były SmallFile. Zauważ, że potrzebujesz kropki po nazwie pliku. Wynikiem powinno być wygenerowanie nowych plików takich jak ten:

SmallFile.ab SmallFile.ad SmallFile.af SmallFile.ah SmallFile.aj
SmallFile.aa SmallFile.ac SmallFile.ae SmallFile.ag SmallFile.ai SmallFile.ak
...

Podziel według liczby linii

W ten sposób podzielisz plik tekstowy na mniejsze pliki ograniczone do 50 linii.

split -l 50 text_to_split.txt

Wynik powinien być mniej więcej taki:

xaa xab xac ...

Podziel według bajtów

Podziel na małe pliki o niestandardowym rozmiarze małych plików w bajtach:

split -b 2048 BigFile.mp4

Wynik powinien być podobny do wyniku z podziału według liczby linii .

Dołączanie plików

Możesz łączyć pliki na dwa sposoby. Pierwszy to:

cat SmallFile.* > OutputBigVideoFile.avi

lub z:

cat SmallFile.?? > OutputBigVideoFile.avi

Uwaga: podczas łączenia plików małe pliki nie powinny być uszkodzone. Również wszystkie małe (częściowe) pliki powinny znajdować się w tym samym katalogu.

Nole
źródło