Löschen Sie die ersten n Bytes der Dateien

32

Ich habe ein extremes Problem und alle Lösungen, die ich mir vorstellen kann, sind kompliziert. Nach meiner Erfahrung mit UNIX / Linux muss es einen einfachen Weg geben.

Ich möchte die ersten 31 Bytes jeder Datei in löschen /foo/. Jede Datei ist lang genug. Ich bin sicher, jemand wird mir eine überraschend einfache Lösung liefern, die ich mir nicht vorstellen kann. Vielleicht awk?

von der tann
quelle
2
Jede awk / sed / ed-Lösung ist zeilenorientiert. Wenn Sie also nicht wissen, dass die erste Zeile aus mindestens 31 Zeichen besteht, treten Komplikationen auf.
Glenn Jackman

Antworten:

28
for file in /foo/*
do
  if [ -f "$file" ]
  then
    dd if="$file" of="$file.truncated" bs=31 skip=1 && mv "$file.truncated" "$file"
  fi
done

oder schneller, dank Gilles Vorschlag:

for file in /foo/*
    do
      if [ -f $file ]
      then
        tail +32c $file > $file.truncated && mv $file.truncated $file
      fi
    done

Hinweis: Posix-Tail gibt "-c +32" anstelle von "+ 32c" an, aber Solaris-Standard-Tail gefällt nicht:

   $ /usr/bin/tail -c +32 /tmp/foo > /tmp/foo1
    tail: cannot open input

/usr/xpg4/bin/tail ist in Ordnung mit beiden Syntaxen.

jlliagre
quelle
1
Was darauf hindeutet , ddhier ist übertrieben, tailist besser geeignet (einfachere, weniger Risiko eines Killer Tippfehler, keine falschen Nachrichten auf stderr).
Gilles 'SO- hör auf böse zu sein'
Du hast recht. Normalerweise vermeide ich Befehle zur Verarbeitung von Textdateien, wenn ich möglicherweise binäre verarbeite, aber "tail + 32c" wird hier funktionieren.
Juli
1
@jlliagre: Du hast geschrieben cut (sollte das nicht Schwanz sein? ... asis, es funktioniert nicht bei mir ...
Peter.O
Natürlich ist es Schwanz. Entschuldigen Sie die Nichtübereinstimmung.
Juli
@jlliagre: Unter Solaris, sollten Sie /usr/xpg4/binvor /usr/binauf PATH, oder Sie werden in den frühen 1990er Jahren aufgeklebt werden. Viele Unices (z. B. GNU, BusyBox) unterstützen die historische +32cSyntax nicht mehr und meinen damit eine aufgerufene Datei +32c(wie es POSIX erfordert).
Gilles 'SO- hör auf böse zu sein'
12

Mit den folgenden Befehlen werden die ersten 31 Bytes abgeschnitten $file( $file~als temporäre Kopie verwendet):

dd if="$file" of="$file~" bs=1 skip=31
mv "$file~" "$file"

Sie müssen nur findalle Dateien auflisten /foo/und die beiden oben genannten für jeden $filegefundenen ausführen .

Alex
quelle
1
Durch Vertauschen von bs und Überspringen von Werten wird die Leistung erhöht.
Juli
10

tail -c +32gibt seinen Eingang abzüglich der ersten 31 Bytes aus. (Ja, das Argument ist um eins falsch.) Um eine Datei zu bearbeiten, verwenden Sie den Schwamm in einer Schleife. Wenn Sie ihn nicht haben und sich nicht darum kümmern möchten, erledigen Sie ihn in der Shell:

for x in /foo/*; do tail -c +32 "$x" | sponge "$x"; done
for x in /foo/*; do tail -c +32 "$x" >"$x.new" && mv "$x.new" "$x"; done

Wenn die Befehle aus irgendeinem Grund unterbrochen werden (z. B. aufgrund eines Stromausfalls), kann es schwierig sein, herauszufinden, wo Sie aufgehört haben. Das Schreiben der neuen Dateien in ein separates Verzeichnis würde die Sache erleichtern.

mkdir /foo.tmp
cd /foo
for x in *; do tail -c +42 -- "$x" >"/foo.tmp/$x" && rm -- "$x"; done
mv /foo.tmp/* /foo
rmdir /foo.tmp

Wenn die Dateien wirklich groß sind (wie im Beispiel), können Sie eine der in diesem Thread genannten Techniken anwenden .

Gilles 'SO - hör auf böse zu sein'
quelle
2

Sie können Vim im Ex-Modus verwenden:

for each in /foo/*
do
  ex -sc '%!tail -c+32' -cx "$each"
done
  1. % Wählen Sie alle Zeilen aus

  2. ! Führen Sie den Befehl aus

  3. x speichern und schließen

Steven Penny
quelle