* Operating on Files:: How to copy, rename, print, compress, etc.
either one file or several files.
* Shell Commands in Dired:: Running a shell command on the marked files.
+* Shell Command Guessing:: Guessing shell commands for files.
* Transforming File Names:: Using patterns to rename multiple files.
* Comparison in Dired:: Running @code{diff} by way of Dired.
* Subdirectories in Dired:: Adding subdirectories to the Dired buffer.
@xref{Single Shell}, for information about running shell commands
outside Dired.
+@node Shell Command Guessing
+@section Shell Command Guessing
+@cindex guessing shell commands for files (in Dired)
+
+Based upon the name of a file, Dired tries to guess what shell command
+you might want to apply to it. For example, if you have point on a
+file named @file{foo.tar} and you press @kbd{!}, Dired will guess that
+you want to run @samp{tar xvf}, and suggest that as the default shell
+command.
+
+The default is mentioned in brackets and you can type @kbd{M-n} to get
+the default into the minibuffer for editing. If there are several
+commands for a given file, e.g., @samp{xtex} and @samp{dvips} for a
+@file{.dvi} file, you can type @kbd{M-n} several times to see each of
+the matching commands.
+
+Dired only tries to guess a command for a single file, never for a
+list of marked files.
+
+The following variables control guessing of shell commands:
+
+@defvar dired-guess-shell-alist-default
+This variable specifies the predefined rules for guessing shell
+commands suitable for certain files. Set this to @code{nil} to turn
+guessing off. The elements of @code{dired-guess-shell-alist-user}
+(defined by the user) will override these rules.
+@end defvar
+
+@defvar dired-guess-shell-alist-user
+If non-@code{nil}, this variables specifies the user-defined alist of
+file regexps and their suggested commands. These rules take
+precedence over the predefined rules in the variable
+@code{dired-guess-shell-alist-default} (to which they are prepended)
+when @code{dired-do-shell-command} is run). The default is
+@code{nil}.
+
+Each element of the alist looks like
+
+@example
+(@var{regexp} @var{command}@dots{})
+@end example
+
+@noindent
+where each @var{command} can either be a string or a Lisp expression
+that evaluates to a string. If several commands are given, all of
+them will temporarily be pushed onto the history.
+
+A @samp{*} in the shell command stands for the file name that matched
+@var{regexp}. When Emacs invokes the @var{command}, it replaces each
+instance of @samp{*} with the matched file name.
+
+You can set this variable in your Init file. For example, to add
+rules for @samp{.foo} and @samp{.bar} file extensions:
+
+@example
+(setq dired-guess-shell-alist-user
+ (list
+ (list "\\.foo$" "@var{foo-command}") ; fixed rule
+ ;; possibly more rules...
+ (list "\\.bar$" ; rule with condition test
+ '(if @var{condition}
+ "@var{bar-command-1}"
+ "@var{bar-command-2}"))))
+@end example
+
+@noindent
+This will override any predefined rules for the same extensions.
+@end defvar
+
+@defvar dired-guess-shell-case-fold-search
+If this variable is non-@code{nil},
+@code{dired-guess-shell-alist-default} and
+@code{dired-guess-shell-alist-user} are matched case-insensitively.
+The default is @code{t}.
+@end defvar
+
+@defvar dired-guess-shell-gnutar
+If this variable is non-@code{nil}, it specifies the name of the GNU
+Tar executable (e.g., @file{tar} or @file{gtar}). GNU Tar's @samp{z}
+switch is used for compressed archives. If you don't have GNU Tar,
+set this to @code{nil}: a pipe using @command{zcat} is then used
+instead.
+@end defvar
+
+@defvar dired-guess-shell-gzip-quiet
+A non-@code{nil} value of this variable means that @samp{-q} is passed
+to @command{gzip}, possibly overriding a verbose option in the
+@env{GZIP} environment variable. The default is @code{t}.
+@end defvar
+
+@defvar dired-guess-shell-znew-switches nil
+This variable specifies a string of switches passed to @command{znew}.
+An example is @samp{-K} which will make @command{znew} keep a
+@file{.Z} file when it is smaller than the @file{.gz} file. The
+default is @code{nil}: no additional switches are passed to
+@command{znew}.
+@end defvar
+
+@defvar dired-shell-command-history nil
+This variable holds the history list for commands that read
+dired-shell commands.
+@end defvar
+
@node Transforming File Names
@section Transforming File Names in Dired
* Introduction::
* Installation::
* Omitting Files in Dired::
-* Shell Command Guessing::
* Virtual Dired::
* Advanced Mark Commands::
* Multiple Dired Directories::
Omitting uninteresting files from Dired listing
(@pxref{Omitting Files in Dired}).
@item
-Guessing shell commands in Dired buffers
-(@pxref{Shell Command Guessing}).
-@item
Running Dired command in non-Dired buffers
(@pxref{Virtual Dired}).
@item
Dired}), if it is active. @code{dired-find-buffer-nocreate} and
@code{dired-initial-position} respect the value of
@code{dired-find-subdir} (@pxref{Miscellaneous Commands}).
-@code{dired-read-shell-command} uses @code{dired-guess-shell-command}
-(@pxref{Shell Command Guessing}) to offer a smarter default command.
@node Installation
@chapter Installation
(with-eval-after-load 'dired
(require 'dired-x)
;; Set dired-x global variables here. For example:
- ;; (setq dired-guess-shell-gnutar "gtar")
;; (setq dired-x-hands-off-my-keys nil)
))
(add-hook 'dired-mode-hook
call @code{dired-extra-startup}, which in turn calls @code{dired-omit-startup}
in your @code{dired-mode-hook}.
-@node Shell Command Guessing
-@chapter Shell Command Guessing
-@cindex guessing shell commands for files.
-
-Based upon the name of a file, Dired tries to guess what shell
-command you might want to apply to it. For example, if you have point
-on a file named @file{foo.tar} and you press @kbd{!}, Dired will guess
-you want to @samp{tar xvf} it and suggest that as the default shell
-command.
-
-The default is mentioned in brackets and you can type @kbd{M-n} to get
-the default into the minibuffer and then edit it, e.g., to change
-@samp{tar xvf} to @samp{tar tvf}. If there are several commands for a given
-file, e.g., @samp{xtex} and @samp{dvips} for a @file{.dvi} file, you can type
-@kbd{M-n} several times to see each of the matching commands.
-
-Dired only tries to guess a command for a single file, never for a list
-of marked files.
-
-The following variables control guessing of shell commands:
-
-@defvar dired-guess-shell-alist-default
-This variable specifies the predefined rules for guessing shell
-commands suitable for certain files. Set this to @code{nil} to turn
-guessing off. The elements of @code{dired-guess-shell-alist-user}
-(defined by the user) will override these rules.
-@end defvar
-
-@defvar dired-guess-shell-alist-user
-If non-@code{nil}, this variables specifies the user-defined alist of
-file regexps and their suggested commands. These rules take
-precedence over the predefined rules in the variable
-@code{dired-guess-shell-alist-default} (to which they are prepended)
-when @code{dired-do-shell-command} is run). The default is
-@code{nil}.
-
-Each element of the alist looks like
-
-@example
-(@var{regexp} @var{command}@dots{})
-@end example
-
-@noindent
-where each @var{command} can either be a string or a Lisp expression
-that evaluates to a string. If several commands are given, all of
-them will temporarily be pushed onto the history.
-
-A @samp{*} in the shell command stands for the file name that matched
-@var{regexp}. When Emacs invokes the @var{command}, it replaces each
-instance of @samp{*} with the matched file name.
-
-You can set this variable in your @file{~/.emacs}. For example,
-to add rules for @samp{.foo} and @samp{.bar} file extensions, write
-
-@example
-(setq dired-guess-shell-alist-user
- (list
- (list "\\.foo$" "@var{foo-command}");; fixed rule
- ;; possibly more rules...
- (list "\\.bar$";; rule with condition test
- '(if @var{condition}
- "@var{bar-command-1}"
- "@var{bar-command-2}"))))
-@end example
-
-@noindent
-This will override any predefined rules for the same extensions.
-@end defvar
-
-@defvar dired-guess-shell-case-fold-search
-If this variable is non-@code{nil},
-@code{dired-guess-shell-alist-default} and
-@code{dired-guess-shell-alist-user} are matched case-insensitively.
-The default is @code{t}.
-@end defvar
-
-@cindex passing GNU Tar its @samp{z} switch.
-@defvar dired-guess-shell-gnutar
-If this variable is non-@code{nil}, it specifies the name of the GNU
-Tar executable (e.g., @file{tar} or @file{gnutar}). GNU Tar's
-@samp{z} switch is used for compressed archives. If you don't have
-GNU Tar, set this to @code{nil}: a pipe using @command{zcat} is then
-used instead. The default is @code{nil}.
-@end defvar
-
-@cindex @code{gzip}
-@defvar dired-guess-shell-gzip-quiet
-A non-@code{nil} value of this variable means that @samp{-q} is passed
-to @command{gzip}, possibly overriding a verbose option in the @env{GZIP}
-environment variable. The default is @code{t}.
-@end defvar
-
-@cindex @code{znew}
-@defvar dired-guess-shell-znew-switches nil
-This variable specifies a string of switches passed to @command{znew}.
-An example is @samp{-K} which will make @command{znew} keep a @file{.Z}
-file when it is smaller than the @file{.gz} file. The default is
-@code{nil}: no additional switches are passed to @command{znew}.
-@end defvar
-
-@defvar dired-shell-command-history nil
-This variable holds the history list for commands that read
-dired-shell commands.
-@end defvar
-
@node Virtual Dired
@chapter Virtual Dired
** Dired
++++
+*** 'dired-guess-shell-command' moved from dired-x to dired.
+This means that 'dired-do-shell-command' will now provide smarter
+defaults without first having to require 'dired-x'. See the node
+"(emacs) Shell Command Guessing" in the Emacs manual for more details.
+
---
*** 'dired-clean-up-buffers-too' moved from dired-x to dired.
This means that Dired now offers to kill buffers visiting files and
(pop-to-buffer out-buffer))
res)))))
+\f
+;;; Guess shell command
+
+;; * `dired-guess-shell-command' provides smarter defaults for
+;; `dired-read-shell-command'.
+;;
+;; * `dired-guess-shell-command' calls `dired-guess-default' with list of
+;; marked files.
+;;
+;; * Parse `dired-guess-shell-alist-user' and
+;; `dired-guess-shell-alist-default' (in that order) for the first REGEXP
+;; that matches the first file in the file list.
+;;
+;; * If the REGEXP matches all the entries of the file list then evaluate
+;; COMMAND, which is either a string or a Lisp expression returning a
+;; string. COMMAND may be a list of commands.
+;;
+;; * Return this command to `dired-guess-shell-command' which prompts user
+;; with it. The list of commands is put into the list of default values.
+;; If a command is used successfully then it is stored permanently in
+;; `dired-shell-command-history'.
+
+;; Guess what shell command to apply to a file.
+(defvar dired-shell-command-history nil
+ "History list for commands that read dired-shell commands.")
+
+;; Default list of shell commands.
+
+;; NOTE: Use `gunzip -c' instead of `zcat' on `.gz' files. Some do not
+;; install GNU zip's version of zcat.
+
+(autoload 'Man-support-local-filenames "man")
+(autoload 'vc-responsible-backend "vc")
+
+(defvar dired-guess-shell-alist-default
+ (list
+ (list "\\.tar\\'"
+ '(if dired-guess-shell-gnutar
+ (concat dired-guess-shell-gnutar " xvf")
+ "tar xvf")
+ ;; Extract files into a separate subdirectory
+ '(if dired-guess-shell-gnutar
+ (concat "mkdir " (file-name-sans-extension file)
+ "; " dired-guess-shell-gnutar " -C "
+ (file-name-sans-extension file) " -xvf")
+ (concat "mkdir " (file-name-sans-extension file)
+ "; tar -C " (file-name-sans-extension file) " -xvf"))
+ ;; List archive contents.
+ '(if dired-guess-shell-gnutar
+ (concat dired-guess-shell-gnutar " tvf")
+ "tar tvf"))
+
+ ;; REGEXPS for compressed archives must come before the .Z rule to
+ ;; be recognized:
+ (list "\\.tar\\.Z\\'"
+ ;; Untar it.
+ '(if dired-guess-shell-gnutar
+ (concat dired-guess-shell-gnutar " zxvf")
+ (concat "zcat * | tar xvf -"))
+ ;; Optional conversion to gzip format.
+ '(concat "znew" (if dired-guess-shell-gzip-quiet " -q")
+ " " dired-guess-shell-znew-switches))
+
+ ;; gzip'ed archives
+ (list "\\.t\\(ar\\.\\)?gz\\'"
+ '(if dired-guess-shell-gnutar
+ (concat dired-guess-shell-gnutar " zxvf")
+ (concat "gunzip -qc * | tar xvf -"))
+ ;; Extract files into a separate subdirectory
+ '(if dired-guess-shell-gnutar
+ (concat "mkdir " (file-name-sans-extension file)
+ "; " dired-guess-shell-gnutar " -C "
+ (file-name-sans-extension file) " -zxvf")
+ (concat "mkdir " (file-name-sans-extension file)
+ "; gunzip -qc * | tar -C "
+ (file-name-sans-extension file) " -xvf -"))
+ ;; Optional decompression.
+ '(concat "gunzip" (if dired-guess-shell-gzip-quiet " -q" ""))
+ ;; List archive contents.
+ '(if dired-guess-shell-gnutar
+ (concat dired-guess-shell-gnutar " ztvf")
+ (concat "gunzip -qc * | tar tvf -")))
+
+ ;; bzip2'ed archives
+ (list "\\.t\\(ar\\.bz2\\|bz\\)\\'"
+ "bunzip2 -c * | tar xvf -"
+ ;; Extract files into a separate subdirectory
+ '(concat "mkdir " (file-name-sans-extension file)
+ "; bunzip2 -c * | tar -C "
+ (file-name-sans-extension file) " -xvf -")
+ ;; Optional decompression.
+ "bunzip2")
+
+ ;; xz'ed archives
+ (list "\\.t\\(ar\\.\\)?xz\\'"
+ "unxz -c * | tar xvf -"
+ ;; Extract files into a separate subdirectory
+ '(concat "mkdir " (file-name-sans-extension file)
+ "; unxz -c * | tar -C "
+ (file-name-sans-extension file) " -xvf -")
+ ;; Optional decompression.
+ "unxz")
+
+ '("\\.shar\\.Z\\'" "zcat * | unshar")
+ '("\\.shar\\.g?z\\'" "gunzip -qc * | unshar")
+
+ '("\\.e?ps\\'" "ghostview" "xloadimage" "lpr")
+ (list "\\.e?ps\\.g?z\\'" "gunzip -qc * | ghostview -"
+ ;; Optional decompression.
+ '(concat "gunzip" (if dired-guess-shell-gzip-quiet " -q")))
+ (list "\\.e?ps\\.Z\\'" "zcat * | ghostview -"
+ ;; Optional conversion to gzip format.
+ '(concat "znew" (if dired-guess-shell-gzip-quiet " -q")
+ " " dired-guess-shell-znew-switches))
+
+ (list "\\.patch\\'"
+ '(if (eq (ignore-errors (vc-responsible-backend default-directory)) 'Git)
+ "cat * | git apply"
+ "cat * | patch"))
+ (list "\\.patch\\.g?z\\'" "gunzip -qc * | patch"
+ ;; Optional decompression.
+ '(concat "gunzip" (if dired-guess-shell-gzip-quiet " -q")))
+ (list "\\.patch\\.Z\\'" "zcat * | patch"
+ ;; Optional conversion to gzip format.
+ '(concat "znew" (if dired-guess-shell-gzip-quiet " -q")
+ " " dired-guess-shell-znew-switches))
+
+ ;; The following four extensions are useful with dired-man ("N" key)
+ ;; FIXME "man ./" does not work with dired-do-shell-command,
+ ;; because there seems to be no way for us to modify the filename,
+ ;; only the command. Hmph. `dired-man' works though.
+ (list "\\.\\(?:[0-9]\\|man\\)\\'"
+ '(let ((loc (Man-support-local-filenames)))
+ (cond ((eq loc 'man-db) "man -l")
+ ((eq loc 'man) "man ./")
+ (t
+ "cat * | tbl | nroff -man -h | col -b"))))
+ (list "\\.\\(?:[0-9]\\|man\\)\\.g?z\\'"
+ '(let ((loc (Man-support-local-filenames)))
+ (cond ((eq loc 'man-db)
+ "man -l")
+ ((eq loc 'man)
+ "man ./")
+ (t "gunzip -qc * | tbl | nroff -man -h | col -b")))
+ ;; Optional decompression.
+ '(concat "gunzip" (if dired-guess-shell-gzip-quiet " -q")))
+ (list "\\.[0-9]\\.Z\\'"
+ '(let ((loc (Man-support-local-filenames)))
+ (cond ((eq loc 'man-db) "man -l")
+ ((eq loc 'man) "man ./")
+ (t "zcat * | tbl | nroff -man -h | col -b")))
+ ;; Optional conversion to gzip format.
+ '(concat "znew" (if dired-guess-shell-gzip-quiet " -q")
+ " " dired-guess-shell-znew-switches))
+ '("\\.pod\\'" "perldoc" "pod2man * | nroff -man")
+
+ '("\\.dvi\\'" "xdvi" "dvips") ; preview and printing
+ '("\\.au\\'" "play") ; play Sun audiofiles
+ '("\\.mpe?g\\'\\|\\.avi\\'" "xine -p")
+ '("\\.ogg\\'" "ogg123")
+ '("\\.mp3\\'" "mpg123")
+ '("\\.wav\\'" "play")
+ '("\\.uu\\'" "uudecode") ; for uudecoded files
+ '("\\.hqx\\'" "mcvert")
+ '("\\.sh\\'" "sh") ; execute shell scripts
+ '("\\.xbm\\'" "bitmap") ; view X11 bitmaps
+ '("\\.gp\\'" "gnuplot")
+ '("\\.p[bgpn]m\\'" "xloadimage")
+ '("\\.gif\\'" "xloadimage") ; view gif pictures
+ '("\\.tif\\'" "xloadimage")
+ '("\\.png\\'" "display") ; xloadimage 4.1 doesn't grok PNG
+ '("\\.jpe?g\\'" "xloadimage")
+ '("\\.fig\\'" "xfig") ; edit fig pictures
+ '("\\.out\\'" "xgraph") ; for plotting purposes.
+ '("\\.tex\\'" "latex" "tex")
+ '("\\.texi\\(nfo\\)?\\'" "makeinfo" "texi2dvi")
+ '("\\.pdf\\'" "xpdf")
+ '("\\.doc\\'" "antiword" "strings")
+ '("\\.rpm\\'" "rpm -qilp" "rpm -ivh")
+ '("\\.dia\\'" "dia")
+ '("\\.mgp\\'" "mgp")
+
+ ;; Some other popular archivers.
+ (list "\\.zip\\'" "unzip" "unzip -l"
+ ;; Extract files into a separate subdirectory
+ '(concat "unzip" (if dired-guess-shell-gzip-quiet " -q")
+ " -d " (file-name-sans-extension file)))
+ '("\\.zoo\\'" "zoo x//")
+ '("\\.lzh\\'" "lharc x")
+ '("\\.arc\\'" "arc x")
+ '("\\.shar\\'" "unshar")
+ '("\\.rar\\'" "unrar x")
+ '("\\.7z\\'" "7z x")
+
+ ;; Compression.
+ (list "\\.g?z\\'" '(concat "gunzip" (if dired-guess-shell-gzip-quiet " -q")))
+ (list "\\.dz\\'" "dictunzip")
+ (list "\\.bz2\\'" "bunzip2")
+ (list "\\.xz\\'" "unxz")
+ (list "\\.Z\\'" "uncompress"
+ ;; Optional conversion to gzip format.
+ '(concat "znew" (if dired-guess-shell-gzip-quiet " -q")
+ " " dired-guess-shell-znew-switches))
+
+ '("\\.sign?\\'" "gpg --verify"))
+ "Default alist used for shell command guessing.
+See `dired-guess-shell-alist-user'.")
+
+(defun dired-guess-default (files)
+ "Return a shell command, or a list of commands, appropriate for FILES.
+See `dired-guess-shell-alist-user'."
+ (let* ((case-fold-search dired-guess-shell-case-fold-search)
+ (programs
+ (delete-dups
+ (mapcar
+ (lambda (command)
+ (eval command `((file . ,(car files)))))
+ (seq-reduce
+ #'append
+ (mapcar #'cdr
+ (seq-filter (lambda (elem)
+ (seq-every-p
+ (lambda (file)
+ (string-match-p (car elem) file))
+ files))
+ (append dired-guess-shell-alist-user
+ dired-guess-shell-alist-default)))
+ nil)))))
+ (if (length= programs 1)
+ (car programs)
+ programs)))
+
+;;;###autoload
+(defun dired-guess-shell-command (prompt files)
+ "Ask user with PROMPT for a shell command, guessing a default from FILES."
+ (let ((default (dired-guess-default files))
+ default-list val)
+ (if (null default)
+ ;; Nothing to guess
+ (read-shell-command prompt nil 'dired-shell-command-history)
+ (setq prompt (replace-regexp-in-string ": $" " " prompt))
+ (if (listp default)
+ ;; More than one guess
+ (setq default-list default
+ default (car default)
+ prompt (concat
+ prompt
+ (format "{%d guesses} " (length default-list))))
+ ;; Just one guess
+ (setq default-list (list default)))
+ ;; Put the first guess in the prompt but not in the initial value.
+ (setq prompt (concat prompt (format "[%s]: " default)))
+ ;; All guesses can be retrieved with M-n
+ (setq val (read-shell-command prompt nil
+ 'dired-shell-command-history
+ default-list))
+ ;; If we got a return, then return default.
+ (if (equal val "") default val))))
+
\f
;;; Commands that delete or redisplay part of the dired buffer
:type 'boolean
:group 'dired-x)
-(defcustom dired-guess-shell-gnutar
- (catch 'found
- (dolist (exe '("tar" "gtar"))
- (if (with-temp-buffer
- (ignore-errors (call-process exe nil t nil "--version"))
- (and (re-search-backward "GNU tar" nil t) t))
- (throw 'found exe))))
- "If non-nil, name of GNU tar executable.
-\(E.g., \"tar\" or \"gtar\"). The `z' switch will be used with it for
-compressed or gzip'ed tar files. If you don't have GNU tar, set this
-to nil: a pipe using `zcat' or `gunzip -c' will be used."
- ;; Changed from system-type test to testing --version output.
- ;; Maybe test --help for -z instead?
- :version "24.1"
- :type '(choice (const :tag "Not GNU tar" nil)
- (string :tag "Command name"))
- :group 'dired-x)
-
-(defcustom dired-guess-shell-gzip-quiet t
- "Non-nil says pass -q to gzip overriding verbose GZIP environment."
- :type 'boolean
- :group 'dired-x)
-
-(defcustom dired-guess-shell-znew-switches nil
- "If non-nil, then string of switches passed to `znew', example: \"-K\"."
- :type '(choice (const :tag "None" nil)
- (string :tag "Switches"))
- :group 'dired-x)
-
\f
;;; Key bindings
default-directory)))
(shell-command command output-buffer error-buffer)))
-\f
-;;; Guess shell command
-
-;; Brief Description:
-;;
-;; * `dired-do-shell-command' is bound to `!' by dired.el.
-;;
-;; * `dired-guess-shell-command' provides smarter defaults for
-;; dired-aux.el's `dired-read-shell-command'.
-;;
-;; * `dired-guess-shell-command' calls `dired-guess-default' with list of
-;; marked files.
-;;
-;; * Parse `dired-guess-shell-alist-user' and
-;; `dired-guess-shell-alist-default' (in that order) for the first REGEXP
-;; that matches the first file in the file list.
-;;
-;; * If the REGEXP matches all the entries of the file list then evaluate
-;; COMMAND, which is either a string or a Lisp expression returning a
-;; string. COMMAND may be a list of commands.
-;;
-;; * Return this command to `dired-guess-shell-command' which prompts user
-;; with it. The list of commands is put into the list of default values.
-;; If a command is used successfully then it is stored permanently in
-;; `dired-shell-command-history'.
-
-;; Guess what shell command to apply to a file.
-(defvar dired-shell-command-history nil
- "History list for commands that read dired-shell commands.")
-
-;; Default list of shell commands.
-
-;; NOTE: Use `gunzip -c' instead of `zcat' on `.gz' files. Some do not
-;; install GNU zip's version of zcat.
-
-(autoload 'Man-support-local-filenames "man")
-(autoload 'vc-responsible-backend "vc")
-
-(defvar dired-guess-shell-alist-default
- (list
- (list "\\.tar\\'"
- '(if dired-guess-shell-gnutar
- (concat dired-guess-shell-gnutar " xvf")
- "tar xvf")
- ;; Extract files into a separate subdirectory
- '(if dired-guess-shell-gnutar
- (concat "mkdir " (file-name-sans-extension file)
- "; " dired-guess-shell-gnutar " -C "
- (file-name-sans-extension file) " -xvf")
- (concat "mkdir " (file-name-sans-extension file)
- "; tar -C " (file-name-sans-extension file) " -xvf"))
- ;; List archive contents.
- '(if dired-guess-shell-gnutar
- (concat dired-guess-shell-gnutar " tvf")
- "tar tvf"))
-
- ;; REGEXPS for compressed archives must come before the .Z rule to
- ;; be recognized:
- (list "\\.tar\\.Z\\'"
- ;; Untar it.
- '(if dired-guess-shell-gnutar
- (concat dired-guess-shell-gnutar " zxvf")
- (concat "zcat * | tar xvf -"))
- ;; Optional conversion to gzip format.
- '(concat "znew" (if dired-guess-shell-gzip-quiet " -q")
- " " dired-guess-shell-znew-switches))
-
- ;; gzip'ed archives
- (list "\\.t\\(ar\\.\\)?gz\\'"
- '(if dired-guess-shell-gnutar
- (concat dired-guess-shell-gnutar " zxvf")
- (concat "gunzip -qc * | tar xvf -"))
- ;; Extract files into a separate subdirectory
- '(if dired-guess-shell-gnutar
- (concat "mkdir " (file-name-sans-extension file)
- "; " dired-guess-shell-gnutar " -C "
- (file-name-sans-extension file) " -zxvf")
- (concat "mkdir " (file-name-sans-extension file)
- "; gunzip -qc * | tar -C "
- (file-name-sans-extension file) " -xvf -"))
- ;; Optional decompression.
- '(concat "gunzip" (if dired-guess-shell-gzip-quiet " -q" ""))
- ;; List archive contents.
- '(if dired-guess-shell-gnutar
- (concat dired-guess-shell-gnutar " ztvf")
- (concat "gunzip -qc * | tar tvf -")))
-
- ;; bzip2'ed archives
- (list "\\.t\\(ar\\.bz2\\|bz\\)\\'"
- "bunzip2 -c * | tar xvf -"
- ;; Extract files into a separate subdirectory
- '(concat "mkdir " (file-name-sans-extension file)
- "; bunzip2 -c * | tar -C "
- (file-name-sans-extension file) " -xvf -")
- ;; Optional decompression.
- "bunzip2")
-
- ;; xz'ed archives
- (list "\\.t\\(ar\\.\\)?xz\\'"
- "unxz -c * | tar xvf -"
- ;; Extract files into a separate subdirectory
- '(concat "mkdir " (file-name-sans-extension file)
- "; unxz -c * | tar -C "
- (file-name-sans-extension file) " -xvf -")
- ;; Optional decompression.
- "unxz")
-
- '("\\.shar\\.Z\\'" "zcat * | unshar")
- '("\\.shar\\.g?z\\'" "gunzip -qc * | unshar")
-
- '("\\.e?ps\\'" "ghostview" "xloadimage" "lpr")
- (list "\\.e?ps\\.g?z\\'" "gunzip -qc * | ghostview -"
- ;; Optional decompression.
- '(concat "gunzip" (if dired-guess-shell-gzip-quiet " -q")))
- (list "\\.e?ps\\.Z\\'" "zcat * | ghostview -"
- ;; Optional conversion to gzip format.
- '(concat "znew" (if dired-guess-shell-gzip-quiet " -q")
- " " dired-guess-shell-znew-switches))
-
- (list "\\.patch\\'"
- '(if (eq (ignore-errors (vc-responsible-backend default-directory)) 'Git)
- "cat * | git apply"
- "cat * | patch"))
- (list "\\.patch\\.g?z\\'" "gunzip -qc * | patch"
- ;; Optional decompression.
- '(concat "gunzip" (if dired-guess-shell-gzip-quiet " -q")))
- (list "\\.patch\\.Z\\'" "zcat * | patch"
- ;; Optional conversion to gzip format.
- '(concat "znew" (if dired-guess-shell-gzip-quiet " -q")
- " " dired-guess-shell-znew-switches))
-
- ;; The following four extensions are useful with dired-man ("N" key)
- ;; FIXME "man ./" does not work with dired-do-shell-command,
- ;; because there seems to be no way for us to modify the filename,
- ;; only the command. Hmph. `dired-man' works though.
- (list "\\.\\(?:[0-9]\\|man\\)\\'"
- '(let ((loc (Man-support-local-filenames)))
- (cond ((eq loc 'man-db) "man -l")
- ((eq loc 'man) "man ./")
- (t
- "cat * | tbl | nroff -man -h | col -b"))))
- (list "\\.\\(?:[0-9]\\|man\\)\\.g?z\\'"
- '(let ((loc (Man-support-local-filenames)))
- (cond ((eq loc 'man-db)
- "man -l")
- ((eq loc 'man)
- "man ./")
- (t "gunzip -qc * | tbl | nroff -man -h | col -b")))
- ;; Optional decompression.
- '(concat "gunzip" (if dired-guess-shell-gzip-quiet " -q")))
- (list "\\.[0-9]\\.Z\\'"
- '(let ((loc (Man-support-local-filenames)))
- (cond ((eq loc 'man-db) "man -l")
- ((eq loc 'man) "man ./")
- (t "zcat * | tbl | nroff -man -h | col -b")))
- ;; Optional conversion to gzip format.
- '(concat "znew" (if dired-guess-shell-gzip-quiet " -q")
- " " dired-guess-shell-znew-switches))
- '("\\.pod\\'" "perldoc" "pod2man * | nroff -man")
-
- '("\\.dvi\\'" "xdvi" "dvips") ; preview and printing
- '("\\.au\\'" "play") ; play Sun audiofiles
- '("\\.mpe?g\\'\\|\\.avi\\'" "xine -p")
- '("\\.ogg\\'" "ogg123")
- '("\\.mp3\\'" "mpg123")
- '("\\.wav\\'" "play")
- '("\\.uu\\'" "uudecode") ; for uudecoded files
- '("\\.hqx\\'" "mcvert")
- '("\\.sh\\'" "sh") ; execute shell scripts
- '("\\.xbm\\'" "bitmap") ; view X11 bitmaps
- '("\\.gp\\'" "gnuplot")
- '("\\.p[bgpn]m\\'" "xloadimage")
- '("\\.gif\\'" "xloadimage") ; view gif pictures
- '("\\.tif\\'" "xloadimage")
- '("\\.png\\'" "display") ; xloadimage 4.1 doesn't grok PNG
- '("\\.jpe?g\\'" "xloadimage")
- '("\\.fig\\'" "xfig") ; edit fig pictures
- '("\\.out\\'" "xgraph") ; for plotting purposes.
- '("\\.tex\\'" "latex" "tex")
- '("\\.texi\\(nfo\\)?\\'" "makeinfo" "texi2dvi")
- '("\\.pdf\\'" "xpdf")
- '("\\.doc\\'" "antiword" "strings")
- '("\\.rpm\\'" "rpm -qilp" "rpm -ivh")
- '("\\.dia\\'" "dia")
- '("\\.mgp\\'" "mgp")
-
- ;; Some other popular archivers.
- (list "\\.zip\\'" "unzip" "unzip -l"
- ;; Extract files into a separate subdirectory
- '(concat "unzip" (if dired-guess-shell-gzip-quiet " -q")
- " -d " (file-name-sans-extension file)))
- '("\\.zoo\\'" "zoo x//")
- '("\\.lzh\\'" "lharc x")
- '("\\.arc\\'" "arc x")
- '("\\.shar\\'" "unshar")
- '("\\.rar\\'" "unrar x")
- '("\\.7z\\'" "7z x")
-
- ;; Compression.
- (list "\\.g?z\\'" '(concat "gunzip" (if dired-guess-shell-gzip-quiet " -q")))
- (list "\\.dz\\'" "dictunzip")
- (list "\\.bz2\\'" "bunzip2")
- (list "\\.xz\\'" "unxz")
- (list "\\.Z\\'" "uncompress"
- ;; Optional conversion to gzip format.
- '(concat "znew" (if dired-guess-shell-gzip-quiet " -q")
- " " dired-guess-shell-znew-switches))
-
- '("\\.sign?\\'" "gpg --verify"))
-
- "Default alist used for shell command guessing.
-See `dired-guess-shell-alist-user'.")
-
-(defcustom dired-guess-shell-alist-user nil
- "User-defined alist of rules for suggested commands.
-These rules take precedence over the predefined rules in the variable
-`dired-guess-shell-alist-default' (to which they are prepended).
-
-Each element of this list looks like
-
- (REGEXP COMMAND...)
-
-COMMAND will be used if REGEXP matches the file to be processed.
-If several files are to be processed, REGEXP has to match all the
-files.
-
-Each COMMAND can either be a string or a Lisp expression that evaluates
-to a string. If this expression needs to consult the name of the file for
-which the shell commands are being requested, it can access that file name
-as the variable `file'.
-
-If several COMMANDs are given, the first one will be the default
-and the rest will be added temporarily to the history and can be retrieved
-with `previous-history-element' (\\<minibuffer-mode-map>\\[previous-history-element]).
-
-The variable `dired-guess-shell-case-fold-search' controls whether
-REGEXP is matched case-sensitively."
- :group 'dired-x
- :type '(alist :key-type regexp :value-type (repeat sexp)))
-
-(defcustom dired-guess-shell-case-fold-search t
- "If non-nil, `dired-guess-shell-alist-default' and
-`dired-guess-shell-alist-user' are matched case-insensitively."
- :group 'dired-x
- :type 'boolean)
-
-(defun dired-guess-default (files)
- "Return a shell command, or a list of commands, appropriate for FILES.
-See `dired-guess-shell-alist-user'."
- (let* ((case-fold-search dired-guess-shell-case-fold-search)
- (programs
- (delete-dups
- (mapcar
- (lambda (command)
- (eval command `((file . ,(car files)))))
- (seq-reduce
- #'append
- (mapcar #'cdr
- (seq-filter (lambda (elem)
- (seq-every-p
- (lambda (file)
- (string-match-p (car elem) file))
- files))
- (append dired-guess-shell-alist-user
- dired-guess-shell-alist-default)))
- nil)))))
- (if (length= programs 1)
- (car programs)
- programs)))
-
-(defun dired-guess-shell-command (prompt files)
- "Ask user with PROMPT for a shell command, guessing a default from FILES."
- (let ((default (dired-guess-default files))
- default-list val)
- (if (null default)
- ;; Nothing to guess
- (read-shell-command prompt nil 'dired-shell-command-history)
- (setq prompt (replace-regexp-in-string ": $" " " prompt))
- (if (listp default)
- ;; More than one guess
- (setq default-list default
- default (car default)
- prompt (concat
- prompt
- (format "{%d guesses} " (length default-list))))
- ;; Just one guess
- (setq default-list (list default)))
- ;; Put the first guess in the prompt but not in the initial value.
- (setq prompt (concat prompt (format "[%s]: " default)))
- ;; All guesses can be retrieved with M-n
- (setq val (read-shell-command prompt nil
- 'dired-shell-command-history
- default-list))
- ;; If we got a return, then return default.
- (if (equal val "") default val))))
-
\f
;;; Visit all marked files simultaneously
:prefix "dired-"
:group 'dired)
+(defgroup dired-guess nil
+ "Guess shell command in Dired."
+ :prefix "dired-"
+ :group 'dired)
+
;;;###autoload
(defcustom dired-listing-switches (purecopy "-al")
"Switches passed to `ls' for Dired. MUST contain the `l' option.
:type 'boolean
:version "28.1")
+(defcustom dired-guess-shell-case-fold-search t
+ "If non-nil, `dired-guess-shell-alist-default' and
+`dired-guess-shell-alist-user' are matched case-insensitively."
+ :group 'dired-guess
+ :type 'boolean
+ :version "29.1")
+
+(defcustom dired-guess-shell-alist-user nil
+ "User-defined alist of rules for suggested commands.
+These rules take precedence over the predefined rules in the variable
+`dired-guess-shell-alist-default' (to which they are prepended).
+
+Each element of this list looks like
+
+ (REGEXP COMMAND...)
+
+COMMAND will be used if REGEXP matches the file to be processed.
+If several files are to be processed, REGEXP has to match all the
+files.
+
+Each COMMAND can either be a string or a Lisp expression that evaluates
+to a string. If this expression needs to consult the name of the file for
+which the shell commands are being requested, it can access that file name
+as the variable `file'.
+
+If several COMMANDs are given, the first one will be the default
+and the rest will be added temporarily to the history and can be retrieved
+with `previous-history-element' (\\<minibuffer-mode-map>\\[previous-history-element]).
+
+The variable `dired-guess-shell-case-fold-search' controls whether
+REGEXP is matched case-sensitively."
+ :group 'dired-guess
+ :type '(alist :key-type regexp :value-type (repeat sexp))
+ :version "29.1")
+
+(defcustom dired-guess-shell-gnutar
+ (catch 'found
+ (dolist (exe '("tar" "gtar"))
+ (if (with-temp-buffer
+ (ignore-errors (call-process exe nil t nil "--version"))
+ (and (re-search-backward "GNU tar" nil t) t))
+ (throw 'found exe))))
+ "If non-nil, name of GNU tar executable.
+\(E.g., \"tar\" or \"gtar\"). The `z' switch will be used with it for
+compressed or gzip'ed tar files. If you don't have GNU tar, set this
+to nil: a pipe using `zcat' or `gunzip -c' will be used."
+ ;; Changed from system-type test to testing --version output.
+ ;; Maybe test --help for -z instead?
+ :group 'dired-guess
+ :type '(choice (const :tag "Not GNU tar" nil)
+ (string :tag "Command name"))
+ :version "29.1")
+
+(defcustom dired-guess-shell-gzip-quiet t
+ "Non-nil says pass -q to gzip overriding verbose GZIP environment."
+ :group 'dired-guess
+ :type 'boolean
+ :version "29.1")
+
+(defcustom dired-guess-shell-znew-switches nil
+ "If non-nil, then string of switches passed to `znew', example: \"-K\"."
+ :group 'dired-guess
+ :type '(choice (const :tag "None" nil)
+ (string :tag "Switches"))
+ :version "29.1")
+
\f
;;; Internal variables
(should (string-match (regexp-quote command) (nth 0 lines)))
(dired-test--check-highlighting (nth 0 lines) '(8))))
+(ert-deftest dired-guess-default ()
+ (let ((dired-guess-shell-alist-user nil)
+ (dired-guess-shell-alist-default
+ '(("\\.png\\'" "display")
+ ("\\.gif\\'" "display" "xloadimage")
+ ("\\.gif\\'" "feh")
+ ("\\.jpe?g\\'" "xloadimage"))))
+ (should (equal (dired-guess-default '("/tmp/foo.png")) "display"))
+ (should (equal (dired-guess-default '("/tmp/foo.gif"))
+ '("display" "xloadimage" "feh")))
+ (should (equal (dired-guess-default '("/tmp/foo.png" "/tmp/foo.txt"))
+ nil))))
+
(provide 'dired-aux-tests)
;;; dired-aux-tests.el ends here
(should (equal all-but-c
(sort (dired-get-marked-files 'local) #'string<))))))
-(ert-deftest dired-guess-default ()
- (let ((dired-guess-shell-alist-user nil)
- (dired-guess-shell-alist-default
- '(("\\.png\\'" "display")
- ("\\.gif\\'" "display" "xloadimage")
- ("\\.gif\\'" "feh")
- ("\\.jpe?g\\'" "xloadimage"))))
- (should (equal (dired-guess-default '("/tmp/foo.png")) "display"))
- (should (equal (dired-guess-default '("/tmp/foo.gif"))
- '("display" "xloadimage" "feh")))
- (should (equal (dired-guess-default '("/tmp/foo.png" "/tmp/foo.txt"))
- nil))))
-
(ert-deftest dired-x--string-to-number ()
(should (= (dired-x--string-to-number "2.4K") 2457.6))
(should (= (dired-x--string-to-number "2400") 2400))