Massendekomprimieren von GZIP-Dateien ohne GZ-Erweiterung

7

Ich habe eine große Anzahl von Dateien mit Erweiterungen wie .0_1234 .0_4213und .0_4132usw. Einige davon sind gzipkomprimiert und andere sind rohe E-Mails. Ich muss feststellen, welche Dateien komprimiert sind, diese dekomprimieren und alle Dateien in eine gemeinsame Erweiterung umbenennen, sobald alle komprimierten Dateien dekomprimiert sind. Ich habe festgestellt, dass ich mit dem Befehl file bestimmen kann, welche komprimiert werden sollen, dann die Ergebnisse sedabrufen und die Ausgabe auf eine Liste von Dateien reduzieren kann, aber nicht bestimmen kann, wie die scheinbar zufälligen Erweiterungen dekomprimiert werden sollen. Folgendes habe ich bisher

file *|grep gzip| sed -e 's/: .*$//g'

Ich möchte xargsoder etwas verwenden, um die Liste der in der Ausgabe bereitgestellten Dateien zu übernehmen und sie entweder umzubenennen, .gzdamit sie dekomprimiert werden können, oder sie einfach inline zu dekomprimieren.

Nicholas Aplington-Johnson
quelle
Verschieben Sie die komprimierten Dateien entweder in ein neues Verzeichnis / temp oder fügen Sie die Ausgabe der Liste in eine Datei ein. Wenn Sie wissen, dass es sich bei den Dateien nur um komprimierten Text handelt, können Sie die Liste einfach durchlaufen und sie in eine neue Datei umwandeln. Ich
bin

Antworten:

5

Nicht verwenden gzip, zcatstattdessen verwenden, was keine Erweiterung erwartet. Sie können das Ganze auf einmal erledigen. Versuchen Sie es einfach mit zcatder Datei. Wenn dies fehlschlägt, weil sie nicht komprimiert ist, versuchen catSie stattdessen Folgendes:

for f in *; do 
    ( zcat "$f" || cat "$f" ) > temp && 
    mv temp "$f".ext && 
    rm "$f" 
done

Das obige Skript versucht zuerst, in zcatdie Datei zu gelangen, tempund wenn dies fehlschlägt (wenn die Datei nicht im gzip-Format vorliegt), wird es genau das cattun. Dies wird in einer Subshell ausgeführt, um die Ausgabe des ausgeführten Befehls zu erfassen und in eine temporäre Datei ( temp) umzuleiten . Anschließend wird das tempin den ursprünglichen Dateinamen plus eine Erweiterung ( .extin diesem Beispiel) umbenannt und das Original gelöscht.

terdon
quelle
Außerdem möchten Sie wahrscheinlich eine Fehlerprüfung für "$f".extbereits vorhandene. Oder verwenden mv -i.
Derobert
@don_crissti Ich weiß, dass es zcatverwendet wird, gzipaber auf meinem System kann ich zumindest gzipkeine Dateien ohne .gzErweiterung akzeptieren, und dies umgeht dieses Problem. Wie würde ich es auf einmal machen?
Terdon
@derobert true, obwohl ich davon ausgegangen bin, dass das OP dies nicht tun würde, da sie automatisch umbenennen möchten.
Terdon
1
@don_crissti Argh! Nein, hatte ich nicht und ich habe das wesentliche Detail übersehen, dass Sie die Ausgabe an stdout gesendet haben. Ja, das ist ein viel besserer Ansatz. Warum postest du es nicht als Antwort?
Terdon
2
Ein Unterschied zwischen diesem und dem Aufruf gunzipbesteht darin, dass gunzipdie Änderungszeit erhalten bleibt.
Gilles 'SO - hör auf böse zu sein'
4

Sie könnten so etwas tun

for f in ./*
do 
gzip -cdfq "$f" > "${f}".some_ext
done

Dies verarbeitet alle Dateien (auch die unkomprimierten über -f) und schreibt (über -c) die Ausgabe mithilfe der Umleitung in stdout , um den Inhalt jeder Datei auf ihrem .some_extGegenstück zu speichern . Sie können dann die Originale zB mit entfernenbash

shopt extglob
rm -f ./!(*.some_ext)

oder zsh

setopt extendedglob
rm -f ./^*some_ext

Sie können die resultierenden Dateien sogar in einem anderen Verzeichnis speichern (diesmal unter der Annahme, dass Sie die ursprüngliche Erweiterung entfernen möchten), z

for f in *
do 
gzip -cdfq -- "$f" > /some/place/else/"${f%.*}".some_ext
done

und dann alles im aktuellen Verzeichnis entfernen ...

don_crissti
quelle
Wie bei Terdons Antwort wird dadurch nicht vermieden, die unkomprimierten Dateien zu kopieren. Aber wenn Sie sich nicht darum kümmern, ist die -fOption von gzip, nicht komprimierte Daten unverändert weiterzugeben, der richtige Weg, also +1.
Peter Cordes
3

Daraufhin wird eine Liste aller mit gzip komprimierten Dateien angezeigt:

file /path/to/files | grep ': gzip compressed data' | cut -d: -f1

.gzDieser hässliche Hack kann Folgendes bewirken, um eine Erweiterung für komprimierte Dateien zu erstellen:

for file in ./*; do
    if gzip -l "$file" > /dev/null 2>&1; then
        case "$file" in
          *.gz) :;; # The file already has the extension corresponding to its format
          *) mv "$file" "${file}.gz";;
        esac
        # Uncomment the following line to decompress them at the same time
        # gunzip "${file}.gz"
    fi
done
DopeGhoti
quelle