Function: dired-do-create-files
dired-do-create-files is a byte-compiled function defined in
dired-aux.el.gz.
Signature
(dired-do-create-files OP-SYMBOL FILE-CREATOR OPERATION ARG &optional MARKER-CHAR OP1 HOW-TO)
Documentation
Create a new file for each marked file.
Prompt user for a target directory in which to create the new
files. The target may also be a non-directory file, if only
one file is marked. The initial suggestion for target is the
Dired buffer's current directory (or, if dired-dwim-target is
non-nil, the current directory of a neighboring Dired window).
OP-SYMBOL is the symbol for the operation. Function dired-mark-pop-up
will determine whether pop-ups are appropriate for this OP-SYMBOL.
FILE-CREATOR and OPERATION as in dired-create-files.
ARG as in dired-get-marked-files.
Optional arg MARKER-CHAR as in dired-create-files.
Optional arg OP1 is an alternate form for OPERATION if there is
only one file.
Optional arg HOW-TO determines how to treat the target.
If HOW-TO is nil, use file-directory-p to determine if the
target is a directory. If so, the marked file(s) are created
inside that directory.
If HOW-TO is t, target is always treated as a plain file.
Otherwise, HOW-TO should be a function of one argument, TARGET.
If its return value is nil, TARGET is regarded as a plain file.
If it return value is a list, TARGET is a generalized
directory (e.g. some sort of archive). The first element of
this list must be a function with at least four arguments:
operation - as OPERATION above.
rfn-list - list of the relative names for the marked files.
fn-list - list of the absolute names for the marked files.
target - the name of the target itself.
The rest of elements of the list returned by HOW-TO are optional
arguments for the function that is the first element of the list.
This can be useful because by default, copying a single file
would replace the tar file. But this could be overridden to
add or replace entries in the tar file.
For any other return value, TARGET is treated as a directory.
Source Code
;; Defined in /usr/src/emacs/lisp/dired-aux.el.gz
(defun dired-do-create-files (op-symbol file-creator operation arg
&optional marker-char op1
how-to)
"Create a new file for each marked file.
Prompt user for a target directory in which to create the new
files. The target may also be a non-directory file, if only
one file is marked. The initial suggestion for target is the
Dired buffer's current directory (or, if `dired-dwim-target' is
non-nil, the current directory of a neighboring Dired window).
OP-SYMBOL is the symbol for the operation. Function `dired-mark-pop-up'
will determine whether pop-ups are appropriate for this OP-SYMBOL.
FILE-CREATOR and OPERATION as in `dired-create-files'.
ARG as in `dired-get-marked-files'.
Optional arg MARKER-CHAR as in `dired-create-files'.
Optional arg OP1 is an alternate form for OPERATION if there is
only one file.
Optional arg HOW-TO determines how to treat the target.
If HOW-TO is nil, use `file-directory-p' to determine if the
target is a directory. If so, the marked file(s) are created
inside that directory.
If HOW-TO is t, target is always treated as a plain file.
Otherwise, HOW-TO should be a function of one argument, TARGET.
If its return value is nil, TARGET is regarded as a plain file.
If it return value is a list, TARGET is a generalized
directory (e.g. some sort of archive). The first element of
this list must be a function with at least four arguments:
operation - as OPERATION above.
rfn-list - list of the relative names for the marked files.
fn-list - list of the absolute names for the marked files.
target - the name of the target itself.
The rest of elements of the list returned by HOW-TO are optional
arguments for the function that is the first element of the list.
This can be useful because by default, copying a single file
would replace the tar file. But this could be overridden to
add or replace entries in the tar file.
For any other return value, TARGET is treated as a directory."
(or op1 (setq op1 operation))
(let ((ret nil))
(let* ((fn-list (dired-get-marked-files nil arg nil nil t))
(rfn-list (mapcar #'dired-make-relative fn-list))
(dired-one-file ; fluid variable inside dired-create-files
(and (consp fn-list) (null (cdr fn-list)) (car fn-list)))
(target-dir (dired-dwim-target-directory))
(default (and dired-one-file
(not dired-dwim-target) ; Bug#25609
(expand-file-name (file-name-nondirectory
(car fn-list))
target-dir)))
(defaults (dired-dwim-target-defaults fn-list target-dir))
(target (expand-file-name ; fluid variable inside dired-create-files
(minibuffer-with-setup-hook
(lambda ()
(setq-local minibuffer-default-add-function nil)
(setq minibuffer-default defaults))
(dired-mark-read-file-name
(format "%s %%s %s: "
(if dired-one-file op1 operation)
(if (memq op-symbol '(symlink hardlink))
;; Linking operations create links
;; from the prompted file name; the
;; other operations copy (etc) to the
;; prompted file name.
"from" "to"))
target-dir op-symbol arg rfn-list default))))
(into-dir
(progn
(when
(or
(not dired-one-file)
(and dired-create-destination-dirs-on-trailing-dirsep
(directory-name-p target)))
(dired-maybe-create-dirs target))
(cond ((null how-to)
;; Allow users to change the letter case of
;; a directory on a case-insensitive
;; filesystem. If we don't test these
;; conditions up front, file-directory-p
;; below will return t on a case-insensitive
;; filesystem, and Emacs will try to move
;; foo -> foo/foo, which fails.
(if (and (file-name-case-insensitive-p (car fn-list))
(eq op-symbol 'move)
dired-one-file
(string= (downcase
(expand-file-name (car fn-list)))
(downcase
(expand-file-name target)))
(not (string=
(file-name-nondirectory (car fn-list))
(file-name-nondirectory target))))
nil
(file-directory-p target)))
((eq how-to t) nil)
(t (funcall how-to target))))))
(setq ret
(if (and (consp into-dir) (functionp (car into-dir)))
(apply (car into-dir) operation rfn-list fn-list target
(cdr into-dir))
(if (not (or dired-one-file into-dir))
(error "Marked %s: target must be a directory: %s"
operation target))
(if (and (not (file-directory-p (car fn-list)))
(not (file-directory-p target))
(directory-name-p target))
(error "%s: Target directory does not exist: %s"
operation target))
;; rename-file bombs when moving directories unless we do this:
(or into-dir (setq target (directory-file-name target)))
(prog1
(dired-create-files
file-creator operation fn-list
(if into-dir ; target is a directory
;; This function uses fluid variable target when called
;; inside dired-create-files:
(lambda (from)
(expand-file-name (file-name-nondirectory from)
target))
(lambda (_from) target))
marker-char)
(when (or (eq dired-do-revert-buffer t)
(and (functionp dired-do-revert-buffer)
(funcall dired-do-revert-buffer target)))
(dired-fun-in-all-buffers (file-name-directory target) nil
#'revert-buffer))))))
(dired-post-do-command)
;; The return value isn't very well defined but is used by
;; `dired-test-bug30624'.
ret))