7

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?

4

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.

4

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.

  • Worked nice. Do diredp had C-w to move/rename file instead of copy ?. Thanks – azzamsa Oct 8 '18 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 Oct 8 '18 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 Oct 8 '18 at 15:17
  • Now. I use dired-ranger hack for this Thanks. – azzamsa Oct 10 '18 at 20:08
2

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)))
  • Thank you very much. I have a suggestion: after pasting , update (refresh) the dired buffer in order to see the new copied items. – Name Feb 27 '18 at 11:45
  • Another suggestion: to unmark the marked items after pasting. – Name Feb 27 '18 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 Feb 27 '18 at 12:59
2

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.
;; ...
  • There are dired-ranger and ranger available on MELPA. You mean which one? – Name Feb 27 '18 at 10:54
  • well, I didn't know about dired-ranger but from the description it looks like smth you want. – Maxim Kim Feb 27 '18 at 11:50
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)))
)

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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