reddit / emacs

Can dired give information about the location of moved files?

that_guu · 2022-10-06 11:24
So today I wanted to move a file to a specific location, using dired as ususal. By mistake I pressed a key that i shouldn't( I don't remember which one) and the file was moved somewhere but I cannot find where. I used find, and locate but nothing. I don't have a trash can folder on my system so its rather impossible to have moved it there by mistake. Does emacs, or dired provide any sort of "history of moved files" or something similar that will help me find the file?
S_Nathan · 2022-10-06 12:31
In case you didn’t do much else in that emacs session (and it’s still open) you can view the keys and the commands caused by said keys with \`view-lossage\`. By default \`C-h l\` is bound to that command. Maybe that can help you.
arthurno1 · 2022-10-06 14:39
It does not have; but have you checked your *Messages* buffer. It usually echoes "moved ..." or "copied file this to that ...", at least in mine Emacs. I don't know if there exists a package already, but it could be possible to advise renaming functions to save file and location in a list that could be later used to redo the operation, unless the file is deleted of course.
whatacold · 2022-10-07 01:38
You can *try to* rename another file, and when it asks you the target name, type `M-p` and it will give you the last path.
that_guu · 2022-10-07 09:39
I use emacs client, so its impossible to find it..
that_guu · 2022-10-07 09:41
I checked and its says something like "moved 1 out of 1 files" or something like that.
that_guu · 2022-10-07 09:42
I wish I knew that the moment it happened...
whatacold · 2022-10-07 10:53
I think this data is persistent, so you can still give it a try right now if you want to know the path.
S_Nathan · 2022-10-07 11:03
If I recall correctly, emacsclient logs them all the same. But I guess it’s now too long ago to find it.
arthurno1 · 2022-10-07 14:16
Indeed,; I have checked it too now when you say, and it does emit just operation and count of files. It is a super tiny modification, but I am not how sure how to rework it sa an advice, would take me longer time; so here is a one-minut hack (just output name of the original file and target in the same message): ;;; The basic function for half a dozen variations on cp/mv/ln/ln -s (defun dired-create-files (file-creator operation fn-list name-constructor &optional marker-char) "Create one or more new files from a list of existing files FN-LIST. This function also handles querying the user, updating Dired buffers, and displaying a success or failure message. FILE-CREATOR should be a function. It is called once for each file in FN-LIST, and must create a new file, querying the user and updating Dired buffers as necessary. It should accept three arguments: the old file name, the new name, and an argument OK-IF-ALREADY-EXISTS with the same meaning as in `copy-file'. OPERATION should be a capitalized string describing the operation performed (e.g. `Copy'). It is used for error logging. FN-LIST is the list of files to copy (full absolute file names). NAME-CONSTRUCTOR should be a function accepting a single argument, the name of an old file, and returning either the corresponding new file name or nil to skip. If optional argument MARKER-CHAR is non-nil, mark each newly-created file's Dired entry with the character MARKER-CHAR, or with the current marker character if MARKER-CHAR is t." (let (dired-create-files-failures failures skipped (success-count 0) (total (length fn-list))) (let (to overwrite-query overwrite-backup-query) ; for dired-handle-overwrite (dolist (from fn-list) ;; Position point on the current file -- this is useful if ;; handling a number of files to show where we're working at. (dired-goto-file from) (setq to (funcall name-constructor from)) (if (equal to from) (progn (setq to nil) (dired-log "Cannot %s to same file: %s\n" (downcase operation) from))) (if (not to) (setq skipped (cons (dired-make-relative from) skipped)) (let* ((overwrite (file-exists-p to)) (dired-overwrite-confirmed ; for dired-handle-overwrite (and overwrite (let ((help-form (format-message (substitute-command-keys "\ Type \\`SPC' or \\`y' to overwrite file `%s', \\`DEL' or \\`n' to skip to next, \\`ESC' or \\`q' to not overwrite any of the remaining files, \\`!' to overwrite all remaining files with no more questions.") to))) (dired-query 'overwrite-query "Overwrite `%s'?" to)))) ;; must determine if FROM is marked before file-creator ;; gets a chance to delete it (in case of a move). (actual-marker-char (cond ((integerp marker-char) marker-char) (marker-char (dired-file-marker from)) ; slow (t nil)))) ;; Handle the `dired-copy-file' file-creator specially ;; When copying a directory to another directory or ;; possibly to itself or one of its subdirectories. ;; e.g "~/foo/" => "~/test/" ;; or "~/foo/" =>"~/foo/" ;; or "~/foo/ => ~/foo/bar/") ;; In this case the 'name-constructor' have set the destination ;; TO to "~/test/foo" because the old emacs23 behavior ;; of `copy-directory' was to not create the subdirectory ;; and instead copy the contents. ;; With the new behavior of `copy-directory' ;; (similar to the `cp' shell command) we don't ;; need such a construction of the target directory, ;; so modify the destination TO to "~/test/" instead of "~/test/foo/". (let ((destname (file-name-directory to))) (when (and (file-directory-p from) (file-directory-p to) (eq file-creator 'dired-copy-file)) (setq to destname)) ;; If DESTNAME is a subdirectory of FROM, not a symlink, ;; and the method in use is copying, signal an error. (and (eq t (file-attribute-type (file-attributes destname))) (eq file-creator 'dired-copy-file) (file-in-directory-p destname from) (error "Cannot copy `%s' into its subdirectory `%s'" from to))) ;; Check, that `dired-do-symlink' does not create symlinks ;; on different hosts. (when (and (eq file-creator 'make-symbolic-link) (not (equal (file-remote-p from) (file-remote-p to)))) (error "Cannot symlink `%s' to `%s' on another host" from to)) (condition-case err (progn (funcall file-creator from to dired-overwrite-confirmed) (if overwrite ;; If we get here, file-creator hasn't been aborted ;; and the old entry (if any) has to be deleted ;; before adding the new entry. (dired-remove-file to)) (setq success-count (1+ success-count)) (message "%s: %d of %d: %s -> %s" operation success-count total from to) (dired-add-file to actual-marker-char)) (file-error ; FILE-CREATOR aborted (progn (push (dired-make-relative from) failures) (dired-log "%s: `%s' to `%s' failed:\n%s\n" operation from to err)))))))) (cond (dired-create-files-failures (setq failures (nconc failures dired-create-files-failures)) (dired-log-summary (format (ngettext "%s failed for %d file in %d requests" "%s failed for %d files in %d requests" (length failures)) operation (length failures) total) failures)) (failures (dired-log-summary (format (ngettext "%s: %d of %d file failed" "%s: %d of %d files failed" total) operation (length failures) total) failures)) (skipped (dired-log-summary (format (ngettext "%s: %d of %d file skipped" "%s: %d of %d files skipped" total) operation (length skipped) total) skipped)) (t (message (ngettext "%s: %d file done" "%s: %d files done" success-count) operation success-count)))) (dired-move-to-filename)) Looks giant, but it just adds "from" and "to" to the message emitting after the operations are done, this is the only spot changed: (message "%s: %d of %d" operation success-count total) for (message "%s: %d of %d: %s -> %s" operation success-count total from to) I guess other messages in the above function could be changed to emit more informative messages with "from" and "to" targets, but as a quick hack to the Ops question, this should do . New message looks like this: Move: 1 of 1: /home/arthur/repos/apikeys.el -> /home/arthur/apikeys.el Omitting... (Nothing to omit) Move: 1 file done Saving file /home/arthur/.config/emacs/lisp/dired-aux.el... Wrote /home/arthur/.config/emacs/lisp/dired-aux.el Mark set Move: 1 of 2: /home/arthur/repos/counter-1.el -> /home/arthur/counter-1.el Omitting... (Nothing to omit) Move: 2 of 2: /home/arthur/repos/counter-2.el -> /home/arthur/counter-2.el Omitting... (Nothing to omit) Move: 1 of 3: /home/arthur/counter-2.el -> /home/arthur/repos/counter-2.el Omitting... (Nothing to omit) Move: 2 of 3: /home/arthur/counter-1.el -> /home/arthur/repos/counter-1.el Omitting... (Nothing to omit) Move: 3 of 3: /home/arthur/apikeys.el -> /home/arthur/repos/apikeys.el You can install by just copying the above code somewhere in your init file. If someone is willing to produce a better patch and see if they want it in Emacs be my guest, or maybe do it as an advice, but better would be a more thought-through patch.