简体   繁体   English

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

[英]How do I rename an open file in Emacs?

Is there a way to rename an open file in Emacs?有没有办法重命名 Emacs 中的打开文件? While I'm viewing it?我在看的时候? Something like save-as, but the original one should go away.类似另存为的东西,但原来的应该是 go 了。

Yes, with dired mode, you can:是的, dired模式,您可以:

  • Cx d to open dired Cx d打开 dired
  • RET to select directory of current file RET选择当前文件的目录
  • Cx Cj ( dired-jump to the name of the current file, in Dired) Cx Cj ( dired-jump到当前文件的名称,在 Dired 中)
  • R to rename the file (or dired-do-rename ). R重命名文件(或dired-do-rename )。
  • q to go back to the (renamed) file buffer q回到(重命名的)文件缓冲区

The rename is equivalent to a shell mv , but it will also update any open buffers, and unlike mv it will not change the access and modify times on the file in the filesystem.重命名等同于 shell mv ,但它也会更新任何打开的缓冲区,与mv不同的是,它不会更改文件系统中文件的访问和修改时间。

只是为了完整性,因为有些人可能会访问此页面,认为他们会得到 Emacs 的“另存为”功能的答案,即打开文件的 Cx Cw。

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".看看那个页面,那里有另一个非常有用的相关函数,称为“移动缓冲区文件”。

My favorite is the one from Magnars (of emacs rocks screencasts fame.)我最喜欢的是来自 Magnars 的( emacs 摇滚截屏视频成名。)

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.感谢 James Yang 提供正确的版本。

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

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 .您可以 在此处阅读更多相关信息。

If you're using Spacemacs then you get this behavior for free since it comes with an implementation of rename-current-buffer-file (based on magnars) that by default bound to SPC-fR .如果您使用的是Spacemacs,那么您可以免费获得此行为,因为它带有默认绑定到SPC-fRrename-current-buffer-file (基于 magnars)的实现。

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

There is a way very easy, you press the command Mx 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.有一种很简单的方法,你按下命令Mx然后输入vc-rename-file ,之后你只需要在目录中选择当前文件,然后选择新名称。 The buff that has the changed file will be refreshed.具有更改文件的 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

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

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

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

I didn't find any of the proposed solutions sufficient for my needs (buffer selection, overwrite confirmation, fast response, actually working etc.), here's what I'm using:我没有发现任何建议的解决方案足以满足我的需求(缓冲区选择、覆盖确认、快速响应、实际工作等),这就是我正在使用的:

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

bound to Cx Cr for convenience with为方便起见,绑定到Cx Cr

(global-set-key (kbd "C-x C-r") 'rename-buffer-and-file)

I know the post is sooo old but in all the answer I have found, nothing is more simple that what said Emacs in their tutorial:我知道这篇文章太老了,但在我找到的所有答案中,没有什么比他们教程中所说的 Emacs 更简单了:
Mx Dired (launch dired) Mx Dired (启动 dired)
Cx Cq (toggle read only in dired) Cx Cq (在 dired 中切换只读)
change the filename like if it was just a line in a text file:更改文件名,就像它只是文本文件中的一行一样:
prev:上一篇:

  /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~

after:后:

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

Cx Cs (for save the changes) Cx Cs (用于保存更改)
Cx Ck (kill the buffer and return to the file). Cx Ck (杀死缓冲区并返回文件)。

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. shift+c 在文件上,emacs 会要求你为包含文件名的路径指定一个名称,所以你只需提供新名称,然后输入......当然,你必须删除前一个。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM