Wie schneide ich Bytes vom Anfang und Ende einer Datei ab?

7

Ich habe eine Datei mit Papierkorb (binäre Kopf- und Fußzeile) am Anfang und Ende der Datei. Ich würde gerne wissen, wie man diese Bytes nuklearisiert. Nehmen wir als Beispiel 25 Bytes von Anfang an an. Und 2 Bytes vom Ende.

Ich weiß, dass ich Truncate und DD verwenden kann, aber Truncate funktioniert nicht mit einem Stream und es scheint etwas umständlich, zwei Befehle für die Hard-Datei auszuführen. Es wäre schöner, wenn man truncate, wenn man wüsste, wie groß die Datei ist, die Datei zuordnen könnte dd. Oder ob es einen schöneren Weg gibt, dies zu tun?

Evan Carroll
quelle

Antworten:

12

Sie können GNU kombinieren tailund head:

tail -c +26 file | head -c -2

gibt den Inhalt aus, der filebei Byte 26 beginnt und zwei Bytes (minus zwei -2) vor dem Ende stoppt . ( -carbeitet mit Bytes, nicht mit Zeichen.)

Stephen Kitt
quelle
1
Beachten Sie, dass dies tail -c +26Standard ist ( head -c -2nicht).
Stéphane Chazelas
@ StéphaneChazelas Gibt es eine POSIX-kompatible Version des head -c -2Befehls?
Katze
Das funktioniert nicht gut, wenn die Datei Null-Bytes enthält, oder?
Zorglub29
@ Zorglub29 es funktioniert bei mir auch mit null bytes.
Stephen Kitt
4

dd erledigt beides für Sie in einem einzigen Befehl. Stellen Sie die Blockgröße auf 1 Byte ein, überspringen Sie die 25 ersten Bytes, zählen Sie bis zur Dateigröße abzüglich der Überspring- und Endbytes.

100 byte file
file.img

dd if=./file.img of=./trimed_file.img bs=1 skip=25 count=73

Überprüfen Sie die Zahlen, da sie möglicherweise von 0 zählen.

jc__
quelle
ist nicht zu langsam?
Ravexina
Zu langsam? Nur wenn die Datei sehr groß ist wie viele GB. Dann können Sie die Blockgröße anpassen.
jc__
Es dauerte 0m8.319s für eine 1.3 MB Datei. Für die Zählung kann er so etwas wie $(( stat -c% s Test verwenden` - 5)) `Ich denke.
Ravexina
Denken Sie daran, dass Überspringen und Zählen Blöcke und keine Bytes sind. Wählen Sie das größte Vielfache für die Blockgröße. Je näher die Blockgröße an der HD-Puffergröße liegt, desto effizienter und schneller ist der Befehl.
jc__
4
mit bs=1dd macht zwei systemaufrufe für jedes byte, das ist schrecklich langsam. GNU dd hat das count_bytesund skip_bytesdas kann helfen, so etwas zu tundd bs=8192 iflag=count_bytes,skip_bytes skip=25 count=73 < infile > outfile
ilkkachu
2

Mit ksh93:

{ head -c "$n"; } < file <#((n = EOF - 25 - 2 , 25))

Oder um es vor Ort zu tun:

{ head -c "$n"; } < file <#((n = EOF - 25 - 2 , 25)) 1<>; file

Wenn Sie /opt/ast/binvor Ihrem $PATH, werden Sie die bekommen headbuiltin.

  • <#((...))ist ein lseek()Operator. ...wird als arithmetischer Ausdruck interpretiert, wobei EOFdie Länge der Datei ist. Daher weisen wir oben die Länge des anzuzeigenden Teils zu $nund suchen nach 25 Bytes in der Datei.
  • <>; ist ein Open-In-Read + Write-Modus und das Abschneiden, wenn der Befehl erfolgreich umgeleitet wird.
Stéphane Chazelas
quelle