Làm cách nào để đổi tên một tệp đang mở trong Emacs?


237

Có cách nào để đổi tên một tệp đang mở trong Emacs không? Trong khi tôi đang xem nó? Một cái gì đó giống như tiết kiệm, nhưng bản gốc sẽ biến mất.

Câu trả lời:


88

Hãy thử chức năng này từ .emacs của Steve Yegge :

;; nguồn: http://steve.yegge.googlepages.com/my-dot-emacs-file
(defun đổi tên tập tin và bộ đệm (tên mới)
  "Đổi tên cả bộ đệm hiện tại và tệp mà nó đang truy cập vào TÊN MỚI."
  (tương tác "tên mới:")
  (hãy ((tên (tên đệm))
        (tên tệp (tên tệp đệm)))
    (nếu (không phải tên tệp)
        (thông báo "Bộ đệm '% s' không truy cập tệp!" tên)
      (nếu (tên đệm get-đệm)
          (thông báo "Bộ đệm có tên '% s' đã tồn tại!" tên mới)
        (tiên lượng
          (đổi tên tập tin tên mới 1)
          (đổi tên bộ đệm-tên mới)
          (set-visit-file-name new name)
          (bộ-đệm-sửa đổi-p nil)))))))

Hãy xem trang đó, có một chức năng liên quan thực sự hữu ích khác ở đó, được gọi là "move-buffer-file".


1
Lưu ý: phương pháp này không tương thích với (setq uniquify-buffer-name-style 'forward)ý nghĩa nếu bạn có bộ đệm được đặt tên users\index.html(vì bạn đã có bộ đệm khác cho posts\index.html) việc đổi tên sẽ thất bại
dolzenko

(set-buffer-modified-p nil)dường như không cần thiết Nếu bạn gọi rename-file-and-buffermột bộ đệm đã sửa đổi và sau đó cố gắng giết nó, nó sẽ vui vẻ làm điều đó mà không cảnh báo bạn về những thay đổi chưa được lưu.
roldugin

Hàm này cũng sẽ (hơi khó chịu) hỏi bạn một tên mới trước khi kiểm tra xem bộ đệm hiện tại có được liên kết với một tệp không (trong trường hợp đó nó hủy bỏ).
Thomas

338

Có, với diredchế độ, bạn có thể:

  • C-x d để mở dired
  • RET để chọn thư mục của tập tin hiện tại
  • C-x C-j( dired-jumptheo tên của tệp hiện tại, trong Dired)
  • Rđể đổi tên tập tin (hoặc dired-do-rename).
  • q để quay lại bộ đệm tệp (đã đổi tên)

Việc đổi tên tương đương với trình bao mv, nhưng nó cũng sẽ cập nhật bất kỳ bộ đệm mở nào và không giống như mvnó sẽ không thay đổi quyền truy cập và sửa đổi thời gian trên tệp trong hệ thống tệp.


9
Đó không phải là trực tiếp đổi tên tập tin hiện tại.
Pupeno

4
Cx b và bạn trở lại bộ đệm ban đầu. Bạn có thể viết một hàm Elisp để làm điều đó, nhưng tôi nghi ngờ bạn sẽ lưu nhiều tổ hợp phím với nó.
Chris Conway

6
Ngoài ra, thay vì Cx b, bạn có thể nhấn Cx k để trở lại bộ đệm ban đầu.
Yoo

32
Các C-x C-jkhông bị ràng buộc bởi mặc định cho tôi. Làm M-x load-library RET dired-x RETđầu tiên làm cho nó bị ràng buộc.
ntc2

4
Một cách khác nếu C-x C-jkhông liên kết chỉ là thực hiện M-x dired-jumplần đầu tiên. Nó sẽ tự động tải dired-x(điều này cũng sẽ C-x C-jđược xác định từ thời điểm này trở đi).
Fernando Basso

120

Để hoàn thiện, vì một số người có thể truy cập trang này với suy nghĩ họ sẽ nhận được câu trả lời cho tính năng "lưu dưới dạng" của Emacs, đó là Cx Cw cho một tệp đang mở.


Cx Cw hoặc sử dụng menuFile > Save as...
Yoo

Không hoàn toàn "lưu dưới dạng", vì tệp bạn đang chỉnh sửa sẽ vẫn là tệp gốc.
asmeker

11
@asmeker Bạn sai rồi! Sau khi lưu, bạn sẽ chỉnh sửa tệp mới.
Joel G Mathew

3
Một lần nữa, tại sao không có tính năng hạ thấp ý kiến?!
gái

7
Có lẽ asmeker có nghĩa là, "tập tin bạn [đã] chỉnh sửa vẫn sẽ [tồn tại]". Vậy thì có đúng không? Tôi sẽ kiểm tra, nhưng sau đó, bạn không thể đánh giá thấp nhận xét của tôi, hahaha.
Brady Trainor

25

Yêu thích của tôi là một từ Magnars (của đá emacs screencasts danh tiếng.)

Không giống như các lựa chọn thay thế khác, bạn không phải gõ tên từ đầu - bạn có được tên hiện tại để sửa đổi.

(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ảm ơn James Yang cho một phiên bản chính xác.


Điều này KHÔNG hoạt động đúng. Cái này thêm "/" vào cuối tập tin.
huyền thoại mã hóa

2
Cảm ơn đã đăng nó ra cho tôi. Cách SO là sửa câu trả lời, không đăng bài mới, sửa đổi một chút.
Mèo Unun 24/03/2017

15

Đây là một phiên bản mạnh mẽ hơn được điều chỉnh từ 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))

Đẹp một. Bây giờ làm lạnh trong chức năng của tôi.
Felix D.

11

Đây là một phiên bản khác, đó là khá mạnh mẽ và nhận thức được 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)))))))

Bạn có thể đọc thêm về nó ở đây .



4

Có một cách rất dễ dàng, bạn nhấn lệnh Mx và hơn gõ vc-rename-file , sau đó bạn chỉ cần chọn tệp hiện tại của mình trong thư mục, và chọn tên mới. Các buff có tập tin thay đổi sẽ được làm mới.

Nguồn: https://www.gnu.org/software/emacs/manual/html_node/emacs/VC-Delete_002fRename.html


1
Điều này có tác dụng phụ (không nhất thiết là mong muốn) khi thêm các tệp cũ và mới được cam kết vào kiểm soát phiên bản. Nhưng +1 vì nó sử dụng hàm dựng sẵn để (hầu hết) trả lời câu hỏi của OP.
khủng long

3

dựa trên phiên bản phóng đại, tôi đã sửa đổi như dưới đây, đã sửa phần tên tệp 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ái này thì tốt hơn. Phiên bản nam châm đưa ra ở trên KHÔNG hoạt động đúng. Thêm một ký tự "/" ở cuối
thần thoại

-1

Nó có thể đạt được bằng bản sao. shift + c trên tệp và emacs sẽ yêu cầu bạn biểu thị tên cho đường dẫn bao gồm tên tệp, vì vậy bạn chỉ cần cung cấp tên mới và nhập ... tất nhiên, bạn phải Xóa tên cũ.


1
Bạn dường như đang đề cập đến "C" trong chế độ chuyển hướng? Đó là sao chép tệp, không đổi tên tệp, mà (như @ChrisConway đã lưu ý) trong thư mục được thực hiện với "R". Và bên cạnh đó, OP đã yêu cầu đổi tên bộ đệm hiện tại.
Davor Cubranic
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.