From 9b01badf7cf7bb6cd64bc8d39564b46ae74b889f Mon Sep 17 00:00:00 2001 From: Kaushal Modi Date: Tue, 11 Aug 2020 15:16:11 +0200 Subject: [PATCH] Allow Dired to dereference symbolic links when copying * doc/emacs/dired.texi (Operating on Files): Mention the new defcustom (bug#25075). * lisp/dired-aux.el (dired-do-copy): Invert the value of `dired-copy-dereference' in lexical scope when prefix argument is '(4). Update function documentation for the new defcustom. * lisp/dired-aux.el (dired-copy-file): Use `dired-copy-dereference' as the `dereference' argument to `dired-copy-file-recursive'. * lisp/dired-aux.el (dired-copy-file-recursive): Add new optional argument `dereference'. * lisp/dired.el (dired-copy-dereference): New defcustom, defaults to nil. --- doc/emacs/dired.texi | 8 ++++++++ etc/NEWS | 6 ++++++ lisp/dired-aux.el | 25 +++++++++++++++++++------ lisp/dired.el | 6 ++++++ 4 files changed, 39 insertions(+), 6 deletions(-) diff --git a/doc/emacs/dired.texi b/doc/emacs/dired.texi index 4ff1dc1bd94..de449e31c37 100644 --- a/doc/emacs/dired.texi +++ b/doc/emacs/dired.texi @@ -694,6 +694,14 @@ The variable @code{dired-recursive-copies} controls whether to copy directories recursively (like @samp{cp -r}). The default is @code{top}, which means to ask before recursively copying a directory. +@vindex dired-copy-dereference +@cindex follow symbolic links +@cindex dereference symbolic links +The variable @code{dired-copy-dereference} controls whether to copy +symbolic links as links or after dereferencing (like @samp{cp -L}). +The default is @code{nil}, which means that the symbolic links are +copied by creating new ones. + @item D @findex dired-do-delete @kindex D @r{(Dired)} diff --git a/etc/NEWS b/etc/NEWS index ddb42fbb4b6..49c0b8688c4 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -222,6 +222,12 @@ like "+0100" instead of "CET". ** Dired ++++ +*** New used option 'dired-copy-dereference'. +If set, Dired will dereferences symbolic links when copying. This can +be switched off on a per-usage basis by providing 'dired-do-copy' with +a 'C-u' prefix. + *** New user option 'dired-mark-region' affects all Dired commands that mark files. When non-nil and the region is active in Transient Mark mode, then Dired commands operate only on files in the active diff --git a/lisp/dired-aux.el b/lisp/dired-aux.el index 69b175339ab..c197ed04fe2 100644 --- a/lisp/dired-aux.el +++ b/lisp/dired-aux.el @@ -1604,7 +1604,7 @@ Special value `always' suppresses confirmation." (defun dired-copy-file (from to ok-flag) (dired-handle-overwrite to) (dired-copy-file-recursive from to ok-flag dired-copy-preserve-time t - dired-recursive-copies)) + dired-recursive-copies dired-copy-dereference)) (declare-function make-symbolic-link "fileio.c") @@ -1627,7 +1627,8 @@ If `ask', ask for user confirmation." (dired-create-directory dir)))) (defun dired-copy-file-recursive (from to ok-flag &optional - preserve-time top recursive) + preserve-time top recursive + dereference) (when (and (eq t (file-attribute-type (file-attributes from))) (file-in-directory-p to from)) (error "Cannot copy `%s' into its subdirectory `%s'" from to)) @@ -1639,7 +1640,8 @@ If `ask', ask for user confirmation." (copy-directory from to preserve-time) (or top (dired-handle-overwrite to)) (condition-case err - (if (stringp (file-attribute-type attrs)) + (if (and (not dereference) + (stringp (file-attribute-type attrs))) ;; It is a symlink (make-symbolic-link (file-attribute-type attrs) to ok-flag) (dired-maybe-create-dirs (file-name-directory to)) @@ -2165,6 +2167,9 @@ See HOW-TO argument for `dired-do-create-files'.") ;;;###autoload (defun dired-do-copy (&optional arg) "Copy all marked (or next ARG) files, or copy the current file. +ARG has to be numeric for above functionality. See +`dired-get-marked-files' for more details. + When operating on just the current file, prompt for the new name. When operating on multiple or marked files, prompt for a target @@ -2178,10 +2183,18 @@ If `dired-copy-preserve-time' is non-nil, this command preserves the modification time of each old file in the copy, similar to the \"-p\" option for the \"cp\" shell command. -This command copies symbolic links by creating new ones, similar -to the \"-d\" option for the \"cp\" shell command." +This command copies symbolic links by creating new ones, +similar to the \"-d\" option for the \"cp\" shell command. +But if `dired-copy-dereference' is non-nil, the symbolic +links are dereferenced and then copied, similar to the \"-L\" +option for the \"cp\" shell command. If ARG is a cons with +element 4 (`\\[universal-argument]'), the inverted value of +`dired-copy-dereference' will be used." (interactive "P") - (let ((dired-recursive-copies dired-recursive-copies)) + (let ((dired-recursive-copies dired-recursive-copies) + (dired-copy-dereference (if (equal arg '(4)) + (not dired-copy-dereference) + dired-copy-dereference))) (dired-do-create-files 'copy #'dired-copy-file "Copy" arg dired-keep-marker-copy diff --git a/lisp/dired.el b/lisp/dired.el index d19d6d1581d..77bb6cfa9ca 100644 --- a/lisp/dired.el +++ b/lisp/dired.el @@ -216,6 +216,12 @@ The target is used in the prompt for file copy, rename etc." :type 'boolean :group 'dired) +(defcustom dired-copy-dereference nil + "If non-nil, Dired dereferences symlinks when copying them. +This is similar to the \"-L\" option for the \"cp\" shell command." + :type 'boolean + :group 'dired) + ; ; These variables were deleted and the replacements are on files.el. ; We leave aliases behind for back-compatibility. (define-obsolete-variable-alias 'dired-free-space-program -- 2.39.5