如何在Emacs中重命名一个打开文件?

时间:2022-10-03 10:48:21

Is there a way to rename an open file in Emacs? While I'm viewing it? Something like save-as, but the original one should go away.

是否有一种方法可以重命名Emacs中的打开文件?当我查看吗?像这样的东西,但是原始的东西应该消失。

9 个解决方案

#1


77  

Try this function from Steve Yegge's .emacs:

试试Steve Yegge的。emacs:

;; source: http://steve.yegge.googlepages.com/my-dot-emacs-file
(defun rename-file-and-buffer (new-name)
  "Renames both current buffer and file it's visiting to NEW-NAME."
  (interactive "sNew name: ")
  (let ((name (buffer-name))
        (filename (buffer-file-name)))
    (if (not filename)
        (message "Buffer '%s' is not visiting a file!" name)
      (if (get-buffer new-name)
          (message "A buffer named '%s' already exists!" new-name)
        (progn
          (rename-file filename new-name 1)
          (rename-buffer new-name)
          (set-visited-file-name new-name)
          (set-buffer-modified-p nil))))))

Take a look at that page, there's another really useful related function there, called "move-buffer-file".

看一下这个页面,这里还有一个非常有用的相关函数,叫做“move-buffer-file”。

#2


288  

Yes, with dired mode, you can:

是的,使用dired模式,您可以:

  • C-x C-j (dired-jump to the name of the current file, in Dired)
  • C-x C-j (Dired -跳转到当前文件的名称,在Dired中)
  • R to rename the file (or dired-do-rename).
  • 重命名文件(或重命名重命名)。
  • C-x k RET to go back to the (renamed) file buffer
  • C-x k RET返回(重命名)文件缓冲区。

The rename is equivalent to a shell mv, but it will also update any open buffers.

重命名等同于shell mv,但是它也会更新任何打开的缓冲区。

#3


112  

Just for completeness, since some folks may visit this page thinking they will get an answer for the "save as" feature of Emacs, that's C-x C-w for an open file.

只是为了完整性,因为有些人可能会访问这个页面,以为他们会得到Emacs的“save as”特性的答案,即C-x C-w,用于打开文件。

#4


20  

My favorite is the one from Magnars (of emacs rocks screencasts fame.)

我最喜欢的是来自马格纳斯(emacs rocks)的一个名人。

Unlike the other alternatives, you don't have to type the name out from scratch - you get the current name to modify.

与其他选项不同,您不必从头开始键入名称——您可以修改当前名称。

(defun rename-current-buffer-file ()
  "Renames current buffer and file it is visiting."
  (interactive)
  (let* ((name (buffer-name))
        (filename (buffer-file-name))
        (basename (file-name-nondirectory filename)))
    (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: " (file-name-directory filename) basename nil basename)))
        (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)))))))

Thanks to James Yang for a correct version.

感谢詹姆斯·杨的正确版本。

#5


14  

Here's a more robust version adapted from stevey.

这里有一个更健壮的版本,改编自stevey。

;; Originally from stevey, adapted to support moving to a new directory.
(defun rename-file-and-buffer (new-name)
  "Renames both current buffer and file it's visiting to NEW-NAME."
  (interactive
   (progn
     (if (not (buffer-file-name))
         (error "Buffer '%s' is not visiting a file!" (buffer-name)))
     ;; Disable ido auto merge since it too frequently jumps back to the original
     ;; file name if you pause while typing. Reenable with C-z C-z in the prompt.
     (let ((ido-auto-merge-work-directories-length -1))
       (list (read-file-name (format "Rename %s to: " (file-name-nondirectory
                                                       (buffer-file-name))))))))
  (if (equal new-name "")
      (error "Aborted rename"))
  (setq new-name (if (file-directory-p new-name)
                     (expand-file-name (file-name-nondirectory
                                        (buffer-file-name))
                                       new-name)
                   (expand-file-name new-name)))
  ;; Only rename if the file was saved before. Update the
  ;; buffer name and visited file in all cases.
  (if (file-exists-p (buffer-file-name))
      (rename-file (buffer-file-name) new-name 1))
  (let ((was-modified (buffer-modified-p)))
    ;; This also renames the buffer, and works with uniquify
    (set-visited-file-name new-name)
    (if was-modified
        (save-buffer)
      ;; Clear buffer-modified flag caused by set-visited-file-name
      (set-buffer-modified-p nil)))

  (setq default-directory (file-name-directory new-name))

  (message "Renamed to %s." new-name))

#6


10  

Here's another version, that's pretty robust and VC aware:

这是另一个版本,非常健壮,VC意识到

(defun rename-file-and-buffer ()
  "Rename the current buffer and file it is visiting."
  (interactive)
  (let ((filename (buffer-file-name)))
    (if (not (and filename (file-exists-p filename)))
        (message "Buffer is not visiting a file!")
      (let ((new-name (read-file-name "New name: " filename)))
        (cond
         ((vc-backend filename) (vc-rename-file filename new-name))
         (t
          (rename-file filename new-name t)
          (set-visited-file-name new-name t t)))))))

You can read more about it here.

你可以在这里读到更多。

#7


3  

There is a way very easy, you press the command M-x and than type vc-rename-file, after that you just need to select your current file at the directory, and than choose the new name. The buff that has the changed file will be refreshed.

有一种非常简单的方法,您按下命令M-x,而不是type vc-rename-file,之后只需要在目录中选择当前文件,而不是选择新名称。已更改文件的buff将被刷新。

Source:https://www.gnu.org/software/emacs/manual/html_node/emacs/VC-Delete_002fRename.html

来源:https://www.gnu.org/software/emacs/manual/html_node/emacs/VC-Delete_002fRename.html

#8


2  

based on magnars version, I modified as below, fixed the INIT file name part:

基于magnars的版本,我修改如下,修正了INIT文件名部分:

(defun rename-current-buffer-file ()
  "Renames current buffer and file it is visiting."
  (interactive)
  (let* ((name (buffer-name))
        (filename (buffer-file-name))
        (basename (file-name-nondirectory filename)))
    (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: " (file-name-directory filename) basename nil basename)))
        (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)))))))

#9


-1  

It can be achieved by copy. shift+c on the file and emacs will ask you to denote a name for the path including the file name, so you just provide the new name,and enter...of course, you have to Delete the former one.

它可以通过复制来实现。文件和emacs上的shift+c将要求您指示路径的名称,包括文件名,所以您只需提供新名称,然后输入…当然,你必须删除前一个。

#1


77  

Try this function from Steve Yegge's .emacs:

试试Steve Yegge的。emacs:

;; source: http://steve.yegge.googlepages.com/my-dot-emacs-file
(defun rename-file-and-buffer (new-name)
  "Renames both current buffer and file it's visiting to NEW-NAME."
  (interactive "sNew name: ")
  (let ((name (buffer-name))
        (filename (buffer-file-name)))
    (if (not filename)
        (message "Buffer '%s' is not visiting a file!" name)
      (if (get-buffer new-name)
          (message "A buffer named '%s' already exists!" new-name)
        (progn
          (rename-file filename new-name 1)
          (rename-buffer new-name)
          (set-visited-file-name new-name)
          (set-buffer-modified-p nil))))))

Take a look at that page, there's another really useful related function there, called "move-buffer-file".

看一下这个页面,这里还有一个非常有用的相关函数,叫做“move-buffer-file”。

#2


288  

Yes, with dired mode, you can:

是的,使用dired模式,您可以:

  • C-x C-j (dired-jump to the name of the current file, in Dired)
  • C-x C-j (Dired -跳转到当前文件的名称,在Dired中)
  • R to rename the file (or dired-do-rename).
  • 重命名文件(或重命名重命名)。
  • C-x k RET to go back to the (renamed) file buffer
  • C-x k RET返回(重命名)文件缓冲区。

The rename is equivalent to a shell mv, but it will also update any open buffers.

重命名等同于shell mv,但是它也会更新任何打开的缓冲区。

#3


112  

Just for completeness, since some folks may visit this page thinking they will get an answer for the "save as" feature of Emacs, that's C-x C-w for an open file.

只是为了完整性,因为有些人可能会访问这个页面,以为他们会得到Emacs的“save as”特性的答案,即C-x C-w,用于打开文件。

#4


20  

My favorite is the one from Magnars (of emacs rocks screencasts fame.)

我最喜欢的是来自马格纳斯(emacs rocks)的一个名人。

Unlike the other alternatives, you don't have to type the name out from scratch - you get the current name to modify.

与其他选项不同,您不必从头开始键入名称——您可以修改当前名称。

(defun rename-current-buffer-file ()
  "Renames current buffer and file it is visiting."
  (interactive)
  (let* ((name (buffer-name))
        (filename (buffer-file-name))
        (basename (file-name-nondirectory filename)))
    (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: " (file-name-directory filename) basename nil basename)))
        (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)))))))

Thanks to James Yang for a correct version.

感谢詹姆斯·杨的正确版本。

#5


14  

Here's a more robust version adapted from stevey.

这里有一个更健壮的版本,改编自stevey。

;; Originally from stevey, adapted to support moving to a new directory.
(defun rename-file-and-buffer (new-name)
  "Renames both current buffer and file it's visiting to NEW-NAME."
  (interactive
   (progn
     (if (not (buffer-file-name))
         (error "Buffer '%s' is not visiting a file!" (buffer-name)))
     ;; Disable ido auto merge since it too frequently jumps back to the original
     ;; file name if you pause while typing. Reenable with C-z C-z in the prompt.
     (let ((ido-auto-merge-work-directories-length -1))
       (list (read-file-name (format "Rename %s to: " (file-name-nondirectory
                                                       (buffer-file-name))))))))
  (if (equal new-name "")
      (error "Aborted rename"))
  (setq new-name (if (file-directory-p new-name)
                     (expand-file-name (file-name-nondirectory
                                        (buffer-file-name))
                                       new-name)
                   (expand-file-name new-name)))
  ;; Only rename if the file was saved before. Update the
  ;; buffer name and visited file in all cases.
  (if (file-exists-p (buffer-file-name))
      (rename-file (buffer-file-name) new-name 1))
  (let ((was-modified (buffer-modified-p)))
    ;; This also renames the buffer, and works with uniquify
    (set-visited-file-name new-name)
    (if was-modified
        (save-buffer)
      ;; Clear buffer-modified flag caused by set-visited-file-name
      (set-buffer-modified-p nil)))

  (setq default-directory (file-name-directory new-name))

  (message "Renamed to %s." new-name))

#6


10  

Here's another version, that's pretty robust and VC aware:

这是另一个版本,非常健壮,VC意识到

(defun rename-file-and-buffer ()
  "Rename the current buffer and file it is visiting."
  (interactive)
  (let ((filename (buffer-file-name)))
    (if (not (and filename (file-exists-p filename)))
        (message "Buffer is not visiting a file!")
      (let ((new-name (read-file-name "New name: " filename)))
        (cond
         ((vc-backend filename) (vc-rename-file filename new-name))
         (t
          (rename-file filename new-name t)
          (set-visited-file-name new-name t t)))))))

You can read more about it here.

你可以在这里读到更多。

#7


3  

There is a way very easy, you press the command M-x and than type vc-rename-file, after that you just need to select your current file at the directory, and than choose the new name. The buff that has the changed file will be refreshed.

有一种非常简单的方法,您按下命令M-x,而不是type vc-rename-file,之后只需要在目录中选择当前文件,而不是选择新名称。已更改文件的buff将被刷新。

Source:https://www.gnu.org/software/emacs/manual/html_node/emacs/VC-Delete_002fRename.html

来源:https://www.gnu.org/software/emacs/manual/html_node/emacs/VC-Delete_002fRename.html

#8


2  

based on magnars version, I modified as below, fixed the INIT file name part:

基于magnars的版本,我修改如下,修正了INIT文件名部分:

(defun rename-current-buffer-file ()
  "Renames current buffer and file it is visiting."
  (interactive)
  (let* ((name (buffer-name))
        (filename (buffer-file-name))
        (basename (file-name-nondirectory filename)))
    (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: " (file-name-directory filename) basename nil basename)))
        (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)))))))

#9


-1  

It can be achieved by copy. shift+c on the file and emacs will ask you to denote a name for the path including the file name, so you just provide the new name,and enter...of course, you have to Delete the former one.

它可以通过复制来实现。文件和emacs上的shift+c将要求您指示路径的名称,包括文件名,所以您只需提供新名称,然后输入…当然,你必须删除前一个。