Jak mogę skrócić plik z linii poleceń?

9

Mam plik xml o pojemności 150 GB, który chciałbym skrócić (tj. Skrócić) do około 1 GB - czy mogę użyć prostej (bash lub podobnej) komendy, której mogę użyć, czy też muszę przejść ścieżkę programową (edycję w vi lub emacs jest koszmarem nawet na dużych żelaznych systemach)?

(Nie jestem szczególnie zaniepokojony utratą informacji, chcę mieć krótszy plik, aby móc na nim przetestować oprogramowanie i nie czekać wiele godzin na odpowiedź, krótszy plik pozwoli mi to zrobić.)

adrianmcmenamin
źródło
1
Czy masz na myśli, że chcesz obciąć plik, czy chcesz usunąć informacje z całego pliku?
AFH
1
Znaleziono to na SO; stackoverflow.com/a/15934078/2800918 .
CAB
2
Ponieważ jest to plik XML, który, jak zakładam, zawiera sekwencję z dużą liczbą elementów, możesz również użyć języka transformacji XML, takiego jak XQuery, aby odfiltrować pewną liczbę tych elementów, co miałoby tę zaletę, że wyprowadzałby prawidłowy XML ( Przykład )
Aaron
4
Czy po zakończeniu plik nadal musi być poprawnym plikiem XML?
Joe
1
nie, właśnie go
załatałem,

Odpowiedzi:

15

Zakładając, że chcesz obciąć i wyodrębnić pierwszy 1 GB ze 150 GB pliku:

Z head:

head -c 1G infile > outfile

Zauważ, że Gsufiks można zastąpić, GBaby wyrównać do 1000 zamiast 1024.

Lub z dd:

dd if=infile of=outfile bs=1M count=1024

Lub jak w odpowiedzi Wumpusa Q. Wumbley ddmoże zostać obcięty w miejscu.

multithr3at3d
źródło
5
Po zakończeniu tej operacji prawdopodobnie nie da się odczytać pliku XML.
Joe
3
@Joe - OP nie zażądał pliku, który można odczytać (ani nie powiedział, że może być nieczytelny). Powiedzieli, że nie dbają o utratę informacji. Spodziewałbym się nowego pytania od OP o tym, jak naprawić wspomniany plik.
KevinDTimm
3
Wiem wystarczająco dużo XML, aby to naprawić, napisałem DTD dla tego formatu!
adrianmcmenamin
37

Aby skrócić plik do 1 gigabajta, użyj truncatepolecenia:

truncate -s 1G file.xml

Wynik obcięcia prawdopodobnie nie będzie prawidłowym plikiem XML, ale rozumiem, że to rozumiesz.

Dokumentacja dla wersji GNU truncatejest tutaj, a dokumentacja dla wersji BSD jest tutaj

John1024
źródło
14

Tam, gdzie to możliwe, truncateużywałbym polecenia jak w odpowiedzi John1024. Nie jest to jednak standardowe polecenie unix, więc może kiedyś nie będziesz mógł go użyć. W takim przypadku ddmożna również wykonać obcinanie na miejscu.

dddomyślnym zachowaniem jest obcięcie pliku wyjściowego w punkcie, w którym kończy się kopiowanie, więc po prostu dajesz mu plik wejściowy o długości 0 i każesz mu rozpocząć zapis w żądanym punkcie obcięcia:

dd if=/dev/null of=filename bs=1048576 seek=1024

(To nie jest to samo, co kopiowanie i obcinanie ddw odpowiedzi multithr3at3d.)

Zauważ, że użyłem 1048576 i 1024, ponieważ 1048576 * 1024 to pożądany rozmiar. I unikać bs = 1m, ponieważ jest to „przenośność” odpowiedź, a klasyczny ddzna tylko przyrostków k, boraz w.


źródło
2
W przypadku ogólnego rozwiązania należy prawdopodobnie zauważyć, że bsliczba pomnożona przez seekliczbę jest liczbą bajtów do zachowania. Wszelkie dwie liczby spełniające to ograniczenie powinny działać; np . bs=1073741824 seek=1lub bs=1 seek=1073741824. Lub, ponieważ bsdomyślnie jest 512, seek=2097152sam powinien również działać. I można użyć notacji jak 1M, 1K, 1Gi 2M.
G-Man mówi „Przywróć Monikę”
1

Nie jestem do końca pewien, o co pytasz. Czy chcesz po prostu pozbyć się pozostałych 149 GB, czy próbujesz skompresować 150 GB do 1 GB? Niezależnie od tego może to być przydatna metoda osiągnięcia tego celu.

splitPolecenie może podzielić każdy plik na kilka kawałków. Zobacz podział człowieka . Możesz określić rozmiar fragmentów pliku, na które chcesz go podzielić za pomocą -bopcji. Na przykład:

$ split -b 1 GB mój_plik.xml

Bez żadnych innych opcji powinno to utworzyć kilka plików w bieżącym katalogu, zaczynając od litery x. Jeśli chcesz zmienić nazwy podzielonych plików, zajrzyj na stronę manuala.

Aby ponownie złożyć plik, wystarczy użyć cat * > re-assembled.xml.

Przykład:

[kent_x86.py@c7 split-test]$ ls -l opendocman*
-rw-rw-r--.  1 kent_x86.py kent_x86.py 2082602 Mar 31  2017 opendocman-1.3.5.tar.gz

[kent_x86.py@c7 split-test]$ split -b 100K opendocman-1.3.5.tar.gz 
[kent_x86.py@c7 split-test]$ ls
opendocman-1.3.5.tar.gz  xaa  xab  xac  xad  xae  xaf  xag  xah  xai  xaj  xak  xal  xam  xan  xao  xap  xaq  xar  xas  xat  xau
[kent_x86.py@c7 split-test]$ ll
total 4072
-rw-rw-r--. 1 kent_x86.py kent_x86.py 2082602 Jan  5 11:06 opendocman-1.3.5.tar.gz
-rw-rw-r--. 1 kent_x86.py kent_x86.py  102400 Jan  5 11:06 xaa
-rw-rw-r--. 1 kent_x86.py kent_x86.py  102400 Jan  5 11:06 xab
-rw-rw-r--. 1 kent_x86.py kent_x86.py  102400 Jan  5 11:06 xac
-rw-rw-r--. 1 kent_x86.py kent_x86.py  102400 Jan  5 11:06 xad
-rw-rw-r--. 1 kent_x86.py kent_x86.py  102400 Jan  5 11:06 xae
-rw-rw-r--. 1 kent_x86.py kent_x86.py  102400 Jan  5 11:06 xaf
-rw-rw-r--. 1 kent_x86.py kent_x86.py  102400 Jan  5 11:06 xag
-rw-rw-r--. 1 kent_x86.py kent_x86.py  102400 Jan  5 11:06 xah
-rw-rw-r--. 1 kent_x86.py kent_x86.py  102400 Jan  5 11:06 xai
-rw-rw-r--. 1 kent_x86.py kent_x86.py  102400 Jan  5 11:06 xaj
-rw-rw-r--. 1 kent_x86.py kent_x86.py  102400 Jan  5 11:06 xak
-rw-rw-r--. 1 kent_x86.py kent_x86.py  102400 Jan  5 11:06 xal
-rw-rw-r--. 1 kent_x86.py kent_x86.py  102400 Jan  5 11:06 xam
-rw-rw-r--. 1 kent_x86.py kent_x86.py  102400 Jan  5 11:06 xan
-rw-rw-r--. 1 kent_x86.py kent_x86.py  102400 Jan  5 11:06 xao
-rw-rw-r--. 1 kent_x86.py kent_x86.py  102400 Jan  5 11:06 xap
-rw-rw-r--. 1 kent_x86.py kent_x86.py  102400 Jan  5 11:06 xaq
-rw-rw-r--. 1 kent_x86.py kent_x86.py  102400 Jan  5 11:06 xar
-rw-rw-r--. 1 kent_x86.py kent_x86.py  102400 Jan  5 11:06 xas
-rw-rw-r--. 1 kent_x86.py kent_x86.py  102400 Jan  5 11:06 xat
-rw-rw-r--. 1 kent_x86.py kent_x86.py   34602 Jan  5 11:06 xau
[kent_x86.py@c7 split-test]$ cat xa* > opendoc-reassembled.tar.gz
[kent_x86.py@c7 split-test]$ ls -l opendoc-reassembled*
-rw-rw-r--. 1 kent_x86.py kent_x86.py 2082602 Jan  5 11:07 opendoc-reassembled.tar.gz
Kentgrav
źródło
0

W końcu użyłem tylko seddo wyodrębnienia dowolnej liczby wierszy:

sed -n 1,1000000p infile.xml>outfile.xml
adrianmcmenamin
źródło
1
Odkładając na bok, czy to odpowiada na pytanie, czy nie, skanuje cały plik, jak sądzę, więc jest o wiele bardziej wydajny w użyciu sed 1000000q(i nieco bardziej zwarty, wizualnie).
Warstwa B