22

Is there a simple M-w C-y approach to copy paste files and directories between two dired buffers?

I mean marking some items (files and buffer) by m then copying them by M-w (or another shortcut), then going to another dired buffer (which is not necessarily in a window side-by-side by the window of previous dired buffer(s)) then yanking all copied file by C-y (or another shortcut) there? This is a simple task that many file explorers in different OS can do.

The problem with the classical Copy option C in dired is that as soon as it is pressed, it asks for the destination. If the path of the destination buffer is very long or there are too many opened dired buffer, this approach is complicated.

I am looking for a solution to first copy the items then to paste them at an appropriate dired buffer.

There is a related question How to quickly copy/move file in Emacs Dired? which uses the classical approach of pressing C when two dired windows separated vertically using the option (setq dired-dwim-target t).

What are the ways to achieve this?

7 Answers 7

16

You can do the following in vanilla Dired (no 3rd-party library needed):

  1. Go first to a Dired buffer that lists the target directory.

  2. With the cursor on the directory header line for a listing of the target directory, use w (command dired-copy-filename-as-kill). This copies the absolute name of that target directory. (You can copy a dir name from any Dired-listing subdir header line in the same way.)

  3. Go to the Dired buffer that lists the files you want to copy. Mark those files.

  4. Use C (command dired-do-copy) to copy the marked files. At the prompt, use C-y to paste the (absolute) name of the target directory. You can just paste it, without bothering to remove the default directory that is inserted in the minibuffer. (Pasting it after that default dir name dims that default name - it is ignored.)

This is, I think, as simple as what you describe (C-w to copy marked file names followed by C-y in the target Dired listing), but the order is opposite: you copy the target directory name first, and then paste it to the C (dired-do-copy) command.

(dired-do-copy checks for existing files of the same name in the target dir, etc.)


Tip: (This is not needed if you use Dired+ - see my other answer here.) If you intend to copy (or move) files from multiple directories to the same target directory, and you might be doing other things with the kill-ring in between, so that the copied target dir name might no longer be first in the kill-ring, then use the secondary selection to select the target dir name. The secondary selection doesn't depend on the region or the position of the cursor - you can paste it as many times as you want, regardless of changes to the kill-ring. You can paste it using the mouse, but it is handier to use C-M-y from library second-sel.el.

1
  • 1
    Thanks, this helped a lot! I struggled with simply moving some files into a newly created subdirectory because the default was the directory on the other side of the split - which is normally nice, but wasn't in this case.
    – xeruf
    Commented Apr 21, 2021 at 9:10
8

I've added this feature now to Dired+.

You can use C-y (command diredp-yank-files) to paste files, whose absolute names you have copied to the kill ring, to the current directory. The "current directory" here is what dired-current-directory returns: the inserted subdirectory where the cursor is located, or the Dired main directory if the cursor is not in a subdir listing.

With a prefix arg, C-y instead prompts you for the target directory for the paste. So you do not need to be in a Dired buffer to paste files to a directory.

You should have copied file names to the kill ring using M-0 w or M-x diredp-copy-abs-filenames-as-kill.

In Dired+ those commands also set variable diredp-last-copied-filenames to the same string of file names. C-y uses the value of that variable, not whatever is currently at the head of the kill ring. This means that you need not paste immediately after you copy file names. And it means that you could, instead of copying file names to the kill ring, just put the names in that variable (e.g. programmatically).

When you use C-y, you are prompted for confirmation (y or n). You can also hit l (for "list") when prompted, to display the list of files that will be pasted.


You can also copy the marked files from the current Dired buffer and any marked files in its marked subdirectories, defined recursively. For that you use M-0 M-+ M-w (zero prefix arg with command diredp-copy-filename-as-kill-recursive) or use M-x diredp-copy-abs-filenames-as-kill-recursive.


Note that with Dired+ you can also easily have a Dired buffer that lists any number of files and directories, from anywhere. That is, the entries listed need not be in the same directory or even in related directories. See C-x D F (command diredp-dired-for-files), which is on the Dir menu-bar menu as item Dired Files Located Anywhere. You can mark and then paste (copy) such arbitrary files from a Dired buffer to any directory.


Update 2019-04-22:

I also added the ability to move (not just paste) the files whose (absolute) names you copied to the kill ring to the current (or another) directory. This is bound to C-w in Dired.

diredp-move-files-named-in-kill-ring is an interactive Lisp function in dired+.el.

(diredp-move-files-named-in-kill-ring &optional DIR NO-CONFIRM-P DETAILS)

Move files, whose absolute names you copied, to the current directory.

With a non-negative prefix arg you are instead prompted for the target directory.

With a non-positive prefix arg you can see details about the files if you hit l when prompted to confirm pasting. Otherwise you see only the file names. The details you see are defined by option diredp-list-file-attributes.

You should have copied the list of file names as a string to the kill ring using M-0 w or M-x diredp-copy-abs-filenames-as-kill. Those commands also set variable diredp-last-copied-filenames to the same string. diredp-move-files-named-in-kill-ring uses the value of that variable, not whatever is currently at the head of the kill ring.

When called from Lisp:

  • Optional arg NO-CONFIRM-P means do not ask for confirmation to move.
  • Optional arg DETAILS is passed to diredp-y-or-n-files-p.
13
  • Worked nice. Do diredp had C-w to move/rename file instead of copy ?. Thanks
    – azzamsa
    Commented Oct 8, 2018 at 8:40
  • @azzamsa: No, I don't think so. (I guess you mean use file names that are on the kill-ring to tell Dired to move those files somewhere, e.g., prompting for where to move them.)
    – Drew
    Commented Oct 8, 2018 at 13:35
  • Sure. I mean why don't you add this functionality ? it would be awesome :). Because the current, only support C-y. Copy only, Not move/rename.
    – azzamsa
    Commented Oct 8, 2018 at 15:17
  • Now. I use dired-ranger hack for this Thanks.
    – azzamsa
    Commented Oct 10, 2018 at 20:08
  • 1
    @HappyFace: Good catch; thx. Forgot to update the recursive command when I added option diredp-filename-separator. Should be fixed now. Please download the latest dired+.el.
    – Drew
    Commented May 10, 2021 at 16:16
4

Your idea sounds straightforward, maybe you can try to implement it by yourself, you can also use the following to get started if you want to.

(defvar your-dired-copy-list nil)

(defun your-dired-copy ()
  (interactive)
  (setq your-dired-copy-list (dired-get-marked-files)))

(defun your-dired-paste ()
  (interactive)
  (when your-dired-copy-list
    (shell-command
     (mapconcat
      #'shell-quote-argument
      `("cp" "-r" ,@your-dired-copy-list ,default-directory)
      " "))
    (setq your-dired-copy-list nil)))
3
  • Thank you very much. I have a suggestion: after pasting , update (refresh) the dired buffer in order to see the new copied items.
    – Name
    Commented Feb 27, 2018 at 11:45
  • Another suggestion: to unmark the marked items after pasting.
    – Name
    Commented Feb 27, 2018 at 11:48
  • @Name Good suggestions. I recommend you implement them by yourself since you are the one who is going to use it. Good luck.
    – xuchunyang
    Commented Feb 27, 2018 at 12:59
3

Ranger file manager works the way you describe, but it is inspired by vim (thus vim keybindings yy to yank/copy p to paste etc). Emacs also has implementation of ranger. Try it, maybe it'll fit your need.

I for myself use emacs sunrise-commander which kind of similar to Midnight Commander (mc), whenever I feel I need double-panes-files-managing.

Upd: dired-ranger has that copy/paste you have described. At least in the docs.

;; Multi-stage copy/pasting of files
;; ---------------------------------

;; A feature present in most orthodox file managers is a "two-stage"
;; copy/paste process.  Roughly, the user first selects some files,
;; "copies" them into a clipboard and then pastes them to the target
;; location.  This workflow is missing in dired.

;; In dired, user first marks the files, then issues the
;; `dired-do-copy' command which prompts for the destination.  The
;; files are then copied there.  The `dired-dwim-target' option makes
;; this a bit friendlier---if two dired windows are opened, the other
;; one is automatically the default target.

;; With the multi-stage operations, you can gather files from
;; *multiple* dired buffers into a single "clipboard", then copy or
;; move all of them to the target location.  Another huge advantage is
;; that if the target dired buffer is already opened, switching to it
;; via ido or ibuffer is often faster than selecting the path.

;; Call `dired-ranger-copy' to add marked files (or the file under
;; point if no files are marked) to the "clipboard".  With non-nil
;; prefix argument, add the marked files to the current clipboard.

;; Past clipboards are stored in `dired-ranger-copy-ring' so you can
;; repeat the past pastes.
;; ...
2
  • There are dired-ranger and ranger available on MELPA. You mean which one?
    – Name
    Commented Feb 27, 2018 at 10:54
  • well, I didn't know about dired-ranger but from the description it looks like smth you want.
    – Maxim Kim
    Commented Feb 27, 2018 at 11:50
2

[The OP posted an answer to his own question but then deleted it - I don't understand why, since it was a perfectly good answer to the question in the title, even though it does not implement what he asked in the body of the question. So for the benefit of future visitors to this question, I will provide his answer - if he decides to undelete his answer in the future, I will delete mine.]

The most convenient way I know to copy (or move) files/directories from one directory to another, is to customize the option dired-dwim-target to t and then open both the source and destination directories in dired: that is much easier than typing a long pathname since you can use completion on paths. Mark the files you want to copy (or move) and then execute the action: C for copy, R for rename. dwim stands for do what I mean and the fact that you have the destination open in dired shows that you mean to copy/move the files to that directory.

One caveat is that if there is a third directory open in dired and shown in a window, dired might mistakenly pick that as the destination directory. But all you have to do is hide it (C-x 0 in the errant directory's window) to tell dired exactly what you mean.

1

I also would suggest to use dired-ranger. This is what I have in my init.el:

(use-package dired-ranger
  :ensure t
  :config
  (setq dired-ranger-copy-ring-size 1)
    (define-key dired-mode-map (kbd "C-w")
        (lambda ()
            (interactive)
            (dired-ranger-copy nil) ; t adds item to dired-ranger-copy-ring
            (define-key dired-mode-map (kbd "C-y") 'dired-ranger-move)))
    (define-key dired-mode-map (kbd "M-w")
        (lambda ()
            (interactive)
            (dired-ranger-copy nil)
            (define-key dired-mode-map (kbd "C-y") 'dired-ranger-paste)))
)
0
0

Dired ranger was the true solution for me:

You can achieve common file explorer behavior as you describe, just with this simple config (assuming you use use-package):

(use-package dired-ranger
  :bind (:map dired-mode-map
              ("W" . dired-ranger-copy)
              ("X" . dired-ranger-move)
              ("Y" . dired-ranger-paste)))

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.