17

My files have long filenames and a part of the filename is a date and a version number. Often I'd like to save the file in the buffer using nearly the same name, just change version number or date.

This would be much easier, if I had a command which puts the filename of the current buffer into the kill ring, so that I can open a file, then type C-x C-w (write file), yank the current name with C-y, change it and save it.

I'm using Emacs 24.3 on Windows and 24.4 on Linux. I have to use different filenames and not git for various reasons. I'd be happy if this command worked with AUCTeX / LaTeX as major mode.


Edit 1:

I made a mistake: I don't want to type C-x C-f (=find file), but C-x C-w (=write file). I corrected this above.

Edit 2:

Found a duplicate question and answer: https://unix.stackexchange.com/a/45381 But there is no better anwswer!

Edit 3:

Here: http://www.gnu.org/software/emacs/manual/html_node/elisp/File-Name-Components.html is a function, which selects the "nondirectory" part of the filname:

Function: file-name-nondirectory filename

This function returns the nondirectory part of filename.

          (file-name-nondirectory "lewis/foo")
               ⇒ "foo"
          (file-name-nondirectory "foo")
               ⇒ "foo"
          (file-name-nondirectory "lewis/")
               ⇒ ""

If I only knew lisp...

  • Oh, hello there Keks :) I've actually wondered this many times myself... good question. And Lisp is easy...... – Sean Allred Oct 30 '14 at 19:56
  • Just found this question... Out of curiosity: are "various reasons" advisor/coauthor-related...? – mbork Dec 11 '14 at 9:04
  • 1
    @mbork I'm a lawyer and write letters as well as contracts. Opening a recent letter to somebody, rename it, erease the content and start writing a new one to the same person is faster than starting from scratch. But regarding to contracts renaming them is a poor substitute for a cvs, but I've never met another lawyer who uses LaTeX and Git, so I have to give to a new version of a contract a new file name... – Keks Dose Dec 11 '14 at 9:10
  • Fair enough. What about YASnippet? It seems very well suited to your use case. – mbork Dec 11 '14 at 14:43
  • @mbork Yes, for my templates I'm using YASnippets, since years. LaTeX, Emacs, orgmode, YASnippets make my PC much more reliable than Word and Outlook. OK, I'm writing this on a Linux machine, but that's something you really can't expect from the usual IT helpdesk: to support Linux instead of Windows. – Keks Dose Dec 11 '14 at 16:36
23

There's no need to do all that.

Simply:

  1. Still in the original file, hit C-x C-w. You will be prompted for a new filename.
  2. Hit M-n, and the current filename will be inserted for you.
  3. Edit what you want and hit RET to save the file to this new name.

You will still have the original file. If you want to go back to it, just visit it again with C-x C-f.

  • I had a look into the Emacs manual about Files/Saving, but did not find this trick. How did you find out? Great! – Keks Dose Oct 30 '14 at 13:12
  • 4
    Not sure. It's a general thing about minibuffer prompts. Hitting M-p goes through the history, and hitting M-n gives you the "current" option. – Malabarba Oct 30 '14 at 13:14
  • 5
    If you are using ido, do C-f first and then M-n. – Kaushal Modi Oct 30 '14 at 13:29
  • 1
    Wow, I never knew this. Thanks! (Sorry for the "thanks, me too" comment, but this is a great example of learning something simple but useful. Viva la emacs.stackexchange! – Mark Aufflick Oct 31 '14 at 2:06
3

Copying the name of file in the current buffer

Here is a function I use from Cameron Desautels' blog that copies the current buffer file name and displays it in minibuffer.

 
;; Source: http://camdez.com/blog/2013/11/14/emacs-show-buffer-file-name/
(defun show-copy-buffer-file-name ()
  "Show the full path to the current file in the minibuffer and also copy it to the kill-ring."
  (interactive)
  (let ((file-name (buffer-file-name)))
    (if file-name
        (progn
          (message file-name)
          (kill-new file-name))
      (error "Buffer not visiting a file"))))

Renaming the name of file in current buffer

Magnar Sveen has implemented the below function in one of his blogs that conveniently renames the current buffer in one go. This is not what you asked for but I thought it could be related to your use case.

;; Source: http://www.whattheemacsd.com/
(defun rename-current-buffer-file ()
  "Renames current buffer and file it is visiting."
  (interactive)
  (let ((name (buffer-name))
        (filename (buffer-file-name)))
    (if (not (and filename (file-exists-p filename)))
        (error "Buffer '%s' is not visiting a file!" name)
      (let ((new-name (read-file-name "New name: " filename)))
        (if (get-buffer new-name)
            (error "A buffer named '%s' already exists!" new-name)
          (rename-file filename new-name 1)
          (rename-buffer new-name)
          (set-visited-file-name new-name)
          (set-buffer-modified-p nil)
          (message "File '%s' successfully renamed to '%s'."
                   name (file-name-nondirectory new-name)))))))
  • The solution by Magnar Sveen deletes the original file and there will only be the renamed file afterwards. This is usefull, but I need to keep the old file as well as the renamed one. The function by Cameron Desautel copies the filename with the whole path. This is quite close to the solution I need. Do you know how to change this function, so that it only spills out the filename without the path? However, thank you very much. – Keks Dose Oct 30 '14 at 11:58
  • 1
    @KeksDose just change (buffer-file-name) to (file-name-nondirectory (buffer-file-name)) in the first function to get filename sans directory. – nispio Oct 30 '14 at 15:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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