在Emacs中,是否有一种方法可以在查看文件时重命名它?类似于另存为,但原始文件应该消失。
是的,使用dired
模式,您可以:
C-x d
打开dired RET
选择当前文件所在目录C-x C-j
(dired-jump
到Dired中当前文件的名称)R
重命名文件(或使用dired-do-rename
)。q
返回(重命名后的)文件缓冲区重命名相当于shell的mv
,但它还会更新任何打开的缓冲区,并且与mv
不同,它不会更改文件在文件系统上的访问和修改时间。
仅为完整性考虑,因为有些人可能会访问此页面以期望得到有关Emacs的“另存为”功能的答案,那么对于已经打开的文件,可以使用C-x C-w。
尝试使用Steve Yegge的.emacs文件中提供的这个函数:
;; 来源:http://steve.yegge.googlepages.com/my-dot-emacs-file (defun rename-file-and-buffer (new-name) "将当前缓冲区和其访问的文件同时重命名为NEW-NAME。" (interactive "s新名称: ") (let ((name (buffer-name)) (filename (buffer-file-name))) (if (not filename) (message "缓冲区 '%s' 没有访问任何文件!" name) (if (get-buffer new-name) (message "名为 '%s' 的缓冲区已经存在!" 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”。
(setq uniquify-buffer-name-style 'forward)
不兼容,这意味着如果您有一个名为users\index.html
的缓冲区(因为您已经有另一个缓冲区用于posts\index.html
),重命名将失败。 - Ev Dolzhenko我最喜欢的是Magnars(来自Emacs Rocks screencasts)的那个。
和其他替代品不同,你不必从头开始键入名称-你可以修改当前名称。
(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提供正确版本。
以下是一个更健壮的版本,改编自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))
(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)))))))
vc-rename-file
命令时出现了这个提示,请在移动文件之前更新它们。 - agent18Emacs 26.3 (2020-04-03)引入了rename-file
函数,可通过M-x rename-file
命令重命名当前文件或其他文件。
emacs 27
中,我做了这个操作,但它只起到了“另存为”的作用。 - Danh Le基于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)))))))
C-x C-j
快捷键。首先执行M-x load-library RET dired-x RET
会使其绑定。 - ntc2C-x C-j
没有被绑定的话,另一个选择是在第一次使用时执行M-x dired-jump
。这将自动加载dired-x
(也会定义从此处开始的C-x C-j
)。 - Fernando Basso