Extrahieren Sie Dateien aus dem Archivmodus auf die Festplatte

Antworten:

7

Hier ist eine Skizze einer Implementierung.

Im Archivierungsmodus werden Zuordnungen von Archivtypen zu Befehlen gespeichert, mit denen Daten in Variablen extrahiert werden archive-TYPE-extract. wir können die richtige Variable finden mit (archive-name "extract").

Alle Befehle sind auf das Extrahieren auf Standard-Out zugeschnitten. stdoutZum Glück können wir sie weiterhin verwenden, wenn wir zu einer Datei unserer Wahl umleiten .

(defun archive-extract-to-file (archive-name item-name command dir)
  "Extract ITEM-NAME from ARCHIVE-NAME using COMMAND. Save to
DIR."
  (unwind-protect
      ;; remove the leading / from the file name to force
      ;; expand-file-name to interpret its path as relative to dir
      (let* ((file-name (if (string-match "\\`/" item-name)
                            (substring item-name 1)
                          item-name))
             (output-file (expand-file-name file-name dir))
             (output-dir (file-name-directory output-file)))
        ;; create the output directory (and its parents) if it does
        ;; not exist yet
        (unless (file-directory-p output-dir)
          (make-directory output-dir t))
        ;; execute COMMAND, redirecting output to output-file
        (apply #'call-process
               (car command)            ;program
               nil                      ;infile
               `(:file ,output-file)    ;destination
               nil                      ;display
               (append (cdr command) (list archive-name item-name))))
    ;; FIXME: add unwind forms
    nil))

Ich habe geändert archive-extract-by-file, um dies zu bekommen.

(defun archive-extract-marked-to-file (output-dir)
  "Extract marked archive items to OUTPUT-DIR."
  (interactive "sOutput directory: ")
  (let ((command (symbol-value (archive-name "extract")))
        (archive (buffer-file-name))
        (items (archive-get-marked ?* t))) ; get marked items; t means
                                           ; get item under point if
                                           ; nothing is marked
    (mapc
     (lambda (item)
       (archive-extract-to-file archive
                                (aref item 0) ; get the name from the descriptor
                                command output-dir))
     items)))

Hier verwende ich mapc, um alle markierten Dateien zu durchlaufen und sie zu extrahieren.

Jetzt müssen wir nur noch eine Schlüsselbindung hinzufügen:

(require 'arc-mode)
(define-key archive-mode-map "F" #'archive-extract-marked-to-file)

Ich habe dies an einer Dummy- .zipDatei getestet, die ein Unterverzeichnis enthält, aber Ihr Kilometerstand kann variieren.

Beachten Sie, dass archive-modeTräger Arc, Lzh, Zip, Zoo, Rar, und 7z. Es ist nicht unterstützen .tgz, .tbz, .tar.gzund Freunde, die geöffnet werden , mit tar-modeund uncompress.el.

Konstantin
quelle
@lawlist: Bitte beachten Sie die aktualisierte Antwort; Jetzt sollte es in der Lage sein, Dateien zu extrahieren, die in Unterverzeichnissen enthalten sind. Beachten Sie, dass die Verzeichnisstruktur neu erstellt wird: foo/bar.txtIn einem Archiv wird nach extrahiert output-dir/foo/bar.txt, nicht nach output-dir/bar.txt. Letzteres ist natürlich möglich, würde aber etwas mehr Code erfordern.
Konstantin
Das ist wirklich schön. Wenn Sie sich damit sicher fühlen, würden Sie in Betracht ziehen, es dem Archivmodus selbst hinzuzufügen?
Malabarba
@ Malabarba: Ja, würde ich. Ich warte gerade auf eine Antwort von [email protected](ich habe diese E-Mail von Lars Ingebrigtsen erhalten ); In der Zwischenzeit werde ich das aufräumen und auf GitHub stellen.
Constantine
Diese neue Funktion ist fantastisch! Vielen Dank - sehr geschätzt! Dies wäre in der Tat eine wunderbare Ergänzung zum Archivierungsmodus. Wie Sie bereits bemerkt haben, wäre die Möglichkeit, auf ein bestimmtes Ausgabeverzeichnis abzuzielen, ohne die Struktur des Zip-Archiv-Verzeichnisses (im Ausgabeverzeichnis) neu zu erstellen, praktisch. Wie es ist, ist es sicherlich ein Häkchen + für die richtige Antwort
wert
Vielen Dank für diesen Code! Eines jedoch: Es ist besser, auf (interactive "G...")diese Weise das aktuelle Verzeichnis vorzuschlagen, und es wird automatisch
vervollständigt