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

有没有办法在Emacs中重命名打开的文件?在我看的时候?类似于另存为,但原始文件应该删除。

84977 次浏览

试试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))))))

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

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

  • C-x d打开干燥
  • RET选择当前文件的目录
  • C-x C-j (dired-jump为当前文件的名称,在Dired中)
  • R重命名文件(或dired-do-rename)。
  • q返回(重命名的)文件缓冲区

重命名相当于shell mv,但它也会更新任何打开的缓冲区,与mv不同的是,它不会改变文件系统中文件的访问和修改时间。

为了完整起见,由于有些人访问此页面时可能认为他们将得到Emacs的“另存为”特性的答案,对于打开的文件,这是C-x C-w。

下面是一个改编自史蒂夫的更健壮的版本。

;; 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))

它可以通过复制来实现。在文件上按Shift +c, emacs将要求您为路径指定一个名称,其中包括文件名,因此只需提供新名称,然后输入…当然,你必须删除前一个。

这是另一个版本,它非常健壮,并且支持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)))))))

你可以阅读更多关于它在这里

我最喜欢的是Magnars (Emacs对屏幕播放很有影响的名声)。

与其他选项不同的是,您不必从头输入名称—您可以获得要修改的当前名称。

(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)))))))

感谢James Yang的正确版本。

基于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)))))))

有一个很简单的方法,你按下命令m x,然后输入vc-rename-file,之后你只需要在目录中选择你当前的文件,然后选择新的名称。已更改文件的buff将被刷新。

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

如果你正在使用Spacemacs,那么你免费得到这个行为,因为它附带了rename-current-buffer-file的实现(基于magnars),默认绑定到SPC-f-R

https://github.com/syl20bnr/spacemacs/blob/bd7ef98e4c35fd87538dd2a81356cc83f5fd02f3/layers/%2Bdistributions/spacemacs-base/funcs.el#L294

Emacs 26.3(2020-04-03)有rename-file函数,可以使用M-x rename-file来重命名当前文件或任何其他文件。

优秀的crux 具有crux-rename-file-and-buffer(以及许多其他有用的函数)。

我没有发现任何建议的解决方案足以满足我的需求(缓冲区选择,覆盖确认,快速响应,实际工作等),以下是我正在使用的:

(defun rename-buffer-and-file (buffer newname)
(interactive "bRename buffer and its visiting file: \nFNew name: ")
(let ((oldname (buffer-file-name)))
(if (not oldname)
(message "Buffer '%s' is not visiting a file" buffer)
(if (file-exists-p newname)
(if (file-directory-p newname)
;; Signal an error if the user specified the name of an
;; existing directory.
(error "%s is a directory" newname)
(unless (y-or-n-p (format-message
"File `%s' exists; overwrite? "
newname))
(error "Canceled"))))
;; Rename buffer and its visiting file
(set-visited-file-name newname)
;; Delete old file
(delete-file oldname)
(save-buffer))))

绑定到C-x C-r以方便使用

(global-set-key (kbd "C-x C-r") 'rename-buffer-and-file)
我知道这篇文章太老了,但在我找到的所有答案中,没有什么比Emacs在他们的教程中说的更简单的了:
M-x Dired (launch dired)
C-x C-q(在dired中切换为只读)
修改文件名,就像它只是文本文件中的一行:
上一页:< / p >
  /home/okiw4n/Documents/project/light_script:
total used in directory 20 available 339.2 GiB
drwxr-xr-x. 2 okiw4n okiw4n 4096 Sep  7 09:07 .
drwxr-xr-x. 3 okiw4n okiw4n 4096 Sep  4 10:03 ..
-rw-r--r--. 1 okiw4n okiw4n 3594 Sep  7 08:39 explication.org
-rw-r--r--. 1 okiw4n okiw4n   85 Sep  4 10:09 script.sh
-rw-r--r--. 1 okiw4n okiw4n 3594 Sep  5 20:08 tuc.org~

后:

  /home/okiw4n/Documents/project/light_script:
total used in directory 20 available 339.2 GiB
drwxr-xr-x. 2 okiw4n okiw4n 4096 Sep  7 09:07 .
drwxr-xr-x. 3 okiw4n okiw4n 4096 Sep  4 10:03 ..
-rw-r--r--. 1 okiw4n okiw4n 3594 Sep  7 08:39 explication.org
-rw-r--r--. 1 okiw4n okiw4n   85 Sep  4 10:09 script.sh
-rw-r--r--. 1 okiw4n okiw4n 3594 Sep  5 20:08 TRUC.org~ (I have rewrite this file)

C-x C-s(用于保存更改)
C-x C-k(结束缓冲区并返回文件).