Function: find-dired

find-dired is an autoloaded, interactive and byte-compiled function defined in find-dired.el.gz.

Signature

(find-dired DIR ARGS)

Documentation

Run find and go into Dired mode on a buffer of the output.

The command run (after changing into DIR) is essentially

    find . \( ARGS \) -ls

except that the car of the variable find-ls-option specifies what to use in place of "-ls" as the final argument.

Collect output in the "*Find*" buffer. To kill the job before it finishes, type M-x kill-find (kill-find).

For more information on how to write valid find expressions for ARGS, see Info node (find) Finding Files. If you are not using GNU findutils (on macOS and *BSD systems), see instead the man page for "find".

Probably introduced at or before Emacs version 19.20.

Key Bindings

Source Code

;; Defined in /usr/src/emacs/lisp/find-dired.el.gz
;;;###autoload
(defun find-dired (dir args)
  "Run `find' and go into Dired mode on a buffer of the output.
The command run (after changing into DIR) is essentially

    find . \\( ARGS \\) -ls

except that the car of the variable `find-ls-option' specifies what to
use in place of \"-ls\" as the final argument.

Collect output in the \"*Find*\" buffer.  To kill the job before
it finishes, type \\[kill-find].

For more information on how to write valid find expressions for
ARGS, see Info node `(find) Finding Files'.  If you are not
using GNU findutils (on macOS and *BSD systems), see instead the
man page for \"find\"."
  (interactive (list (read-directory-name "Run find in directory: " nil "" t)
		     (read-string "Run find (with args): " find-args
				  '(find-args-history . 1))))
  (let ((dired-buffers dired-buffers))
    ;; Expand DIR ("" means default-directory), and make sure it has a
    ;; trailing slash.
    (setq dir (file-name-as-directory (expand-file-name dir)))
    ;; Check that it's really a directory.
    (or (file-directory-p dir)
	(error "find-dired needs a directory: %s" dir))
    (pop-to-buffer-same-window (get-buffer-create "*Find*"))

    ;; See if there's still a `find' running, and offer to kill
    ;; it first, if it is.
    (let ((find (get-buffer-process (current-buffer))))
      (when find
	(if (or (not (eq (process-status find) 'run))
		(yes-or-no-p
		 (format-message "A `find' process is running; kill it? ")))
	    (condition-case nil
		(progn
		  (interrupt-process find)
		  (sit-for 1)
		  (delete-process find))
	      (error nil))
	  (error "Cannot have two processes in `%s' at once" (buffer-name)))))

    (widen)
    (kill-all-local-variables)
    (setq buffer-read-only nil)
    (erase-buffer)
    (setq default-directory dir
	  find-args args	      ; save for next interactive call
	  args (concat find-program " . "
		       (if (string= args "")
			   ""
			 (concat
			  (shell-quote-argument "(")
			  " " args " "
			  (shell-quote-argument ")")
			  " "))
		       (if (string-match "\\`\\(.*\\) {} \\(\\\\;\\|\\+\\)\\'"
					 (car find-ls-option))
			   (format "%s %s %s"
				   (match-string 1 (car find-ls-option))
				   (shell-quote-argument "{}")
				   find-exec-terminator)
			 (car find-ls-option))))
    ;; Start the find process.
    (shell-command (concat args "&") (current-buffer))
    (dired-mode dir (cdr find-ls-option))
    (let ((map (make-sparse-keymap)))
      (set-keymap-parent map (current-local-map))
      (define-key map "\C-c\C-k" 'kill-find)
      (use-local-map map))
    (setq-local dired-sort-inhibit t)
    (setq-local revert-buffer-function
                (lambda (_ignore-auto _noconfirm)
                  (find-dired dir find-args)))
    ;; Set subdir-alist so that Tree Dired will work:
    (if (fboundp 'dired-simple-subdir-alist)
	;; will work even with nested dired format (dired-nstd.el,v 1.15
	;; and later)
	(dired-simple-subdir-alist)
      ;; else we have an ancient tree dired (or classic dired, where
      ;; this does no harm)
      (setq-local dired-subdir-alist
                  (list (cons default-directory (point-min-marker)))))
    (setq-local dired-subdir-switches find-ls-subdir-switches)
    (setq buffer-read-only nil)
    ;; Subdir headlerline must come first because the first marker in
    ;; subdir-alist points there.
    (insert "  " dir ":\n")
    ;; Make second line a ``find'' line in analogy to the ``total'' or
    ;; ``wildcard'' line.
    (let ((point (point)))
      (insert "  " args "\n")
      (dired-insert-set-properties point (point)))
    (setq buffer-read-only t)
    (let ((proc (get-buffer-process (current-buffer))))
      (set-process-filter proc #'find-dired-filter)
      (set-process-sentinel proc #'find-dired-sentinel)
      ;; Initialize the process marker; it is used by the filter.
      (move-marker (process-mark proc) (point) (current-buffer)))
    (setq mode-line-process '(":%s"))))