Here's a sketch of an implementation.
Archive mode stores maps from archive types to commands used to extract data in variables archive-TYPE-extract; we can find the right variable using (archive-name "extract").
All commands are tailored for extracting to standard out; luckily we can still use them if we redirect stdout to a file of our choice.
(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))
I modified archive-extract-by-file to get this.
(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)))
Here I use mapc to loop over all marked files and extract them.
Now we just need to add a key binding:
(require 'arc-mode) (define-key archive-mode-map "F" #'archive-extract-marked-to-file)
I tested this on a dummy .zip file containing a subdirectory, but your mileage may vary.
Note that archive-mode supports Arc, Lzh, Zip, Zoo, Rar, and 7z. It does not support .tgz, .tbz, .tar.gz and friends, which are opened using tar-mode and uncompress.el.