Extraia o (s) arquivo (s) para o disco rígido do `modo de arquivo`

Respostas:

7

Aqui está um esboço de uma implementação.

O modo Arquivar armazena mapas dos tipos de arquivamento para comandos usados ​​para extrair dados em variáveis archive-TYPE-extract; podemos encontrar a variável correta usando (archive-name "extract").

Todos os comandos são personalizados para extrair para saída padrão; felizmente, ainda podemos usá-los se redirecionarmos stdoutpara um arquivo de nossa escolha.

(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))

Eu modifiquei archive-extract-by-filepara conseguir isso.

(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)))

Aqui eu uso mapcpara percorrer todos os arquivos marcados e extraí-los.

Agora só precisamos adicionar uma ligação de chave:

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

Eu testei isso em um .ziparquivo fictício contendo um subdiretório, mas sua milhagem pode variar.

Note-se que archive-modesuportes Arc, Lzh, Zip, Zoo, Rar, e 7z. Ele não apoiar .tgz, .tbz, .tar.gze amigos, que são abertos usando tar-modee uncompress.el.

Constantine
fonte
@lawlist: Veja a resposta atualizada; agora deve poder extrair arquivos contidos em subdiretórios. Observe que ele recria a estrutura de diretórios: foo/bar.txtem um archive é extraído para output-dir/foo/bar.txt, e não para output-dir/bar.txt. O último é possível, é claro, mas exigiria mais código.
Constantine
Isso é muito legal. Depois de se sentir confiante, considere adicioná-lo ao próprio modo de arquivo?
Malabarba
@ Malabarba: Sim, eu faria. Estou aguardando uma resposta de [email protected](recebi este e-mail de Lars Ingebrigtsen ) agora; Enquanto isso, eu vou limpar isso e colocá-lo no GitHub.
Constantine
Este novo recurso é incrível! Muito obrigado - muito apreciado! Isso seria realmente uma adição maravilhosa ao modo de arquivo. Como você observou, a capacidade de direcionar um diretório de saída específico sem necessariamente recriar a estrutura do diretório de arquivo morto (no diretório de saída) seria útil. Como é, certamente é digno de uma marca de verificação + para a resposta correta :)
lawlist
Muito obrigado por este código! Uma coisa, porém: que seria melhor para (interactive "G...")desta forma ele irá sugerir o diretório atual, mais ele vai autocomplete e interagir com o modo Ido etc.
wvxvw