ฉันจะเปลี่ยนชื่อไฟล์ที่เปิดอยู่ใน Emacs ได้อย่างไร


237

มีวิธีการเปลี่ยนชื่อไฟล์ที่เปิดอยู่ใน Emacs หรือไม่? ในขณะที่ฉันกำลังดูมัน สิ่งที่ชอบประหยัด แต่คนดั้งเดิมควรหายไป

คำตอบ:


88

ลองใช้ฟังก์ชันนี้จาก. emacs ของ Steve Yegge :

;; แหล่งที่มา: http://steve.yegge.googlepages.com/my-dot-emacs-file
(defun เปลี่ยนชื่อไฟล์และบัฟเฟอร์ (ชื่อใหม่)
  "เปลี่ยนชื่อทั้งบัฟเฟอร์ปัจจุบันและไฟล์ที่กำลังเยี่ยมชม NEW-NAME"
  (โต้ตอบ "ชื่อใหม่:")
  (let ((ชื่อ (บัฟเฟอร์ชื่อ))
        (ชื่อไฟล์ (บัฟเฟอร์ไฟล์ชื่อ)))
    (ถ้า (ไม่ใช่ชื่อไฟล์)
        (ข้อความ "ชื่อบัฟเฟอร์ '% s' ไม่ได้ไปที่ไฟล์!")
      (ถ้า (รับบัฟเฟอร์ชื่อใหม่)
          (ข้อความ "บัฟเฟอร์ชื่อ '% s' มีอยู่แล้ว!" ชื่อใหม่)
        (progn
          (เปลี่ยนชื่อไฟล์ไฟล์ชื่อใหม่ 1)
          (เปลี่ยนชื่อบัฟเฟอร์ใหม่ชื่อ)
          (ชื่อไฟล์ใหม่ชื่อชุด)
          (set-buffer-modified-p ไม่มีศูนย์)))))

ลองดูที่หน้านั้นมีอีกฟังก์ชั่นที่เกี่ยวข้องมีประโยชน์จริง ๆ เรียกว่า "move-buffer-file"


1
หมายเหตุ: วิธีนี้เข้ากันไม่ได้กับ(setq uniquify-buffer-name-style 'forward)ความหมายถ้าคุณมีบัฟเฟอร์ชื่อusers\index.html(เพราะคุณมีบัฟเฟอร์อื่นแล้วposts\index.html) การเปลี่ยนชื่อจะล้มเหลว
dolzenko

(set-buffer-modified-p nil)ดูเหมือนไม่จำเป็น ถ้าคุณโทรrename-file-and-bufferหาบัฟเฟอร์ที่แก้ไขแล้วและพยายามที่จะฆ่ามันมันจะทำอย่างมีความสุขโดยไม่เตือนคุณเกี่ยวกับการเปลี่ยนแปลงที่ไม่ได้บันทึก
roldugin

ฟังก์ชั่นนี้จะค่อนข้างน่ารำคาญถามชื่อใหม่ก่อนที่จะตรวจสอบว่าบัฟเฟอร์ปัจจุบันมีการเชื่อมโยงกับไฟล์ที่ทุกคน (ในกรณีที่มันยกเลิก)
โทมัส

338

ใช่ด้วยdiredโหมดคุณสามารถ:

  • C-x d เพื่อเปิด dire
  • RET เพื่อเลือกไดเรกทอรีของไฟล์ปัจจุบัน
  • C-x C-j( dired-jumpตามชื่อไฟล์ปัจจุบันใน Dired)
  • Rเพื่อเปลี่ยนชื่อไฟล์ (หรือdired-do-rename)
  • q เพื่อกลับไปที่บัฟเฟอร์ไฟล์ (เปลี่ยนชื่อ)

การเปลี่ยนชื่อนั้นเทียบเท่ากับเชลล์mvแต่มันจะอัพเดตบัฟเฟอร์ที่เปิดอยู่ด้วยซึ่งต่างจากmvมันจะไม่เปลี่ยนการเข้าถึงและแก้ไขเวลาในไฟล์ในระบบไฟล์


9
ไม่ได้เปลี่ยนชื่อไฟล์ปัจจุบันโดยตรง
pupeno

4
Cx b และคุณกลับมาที่บัฟเฟอร์เดิม คุณสามารถเขียนฟังก์ชัน Elisp เพื่อทำได้ แต่ฉันสงสัยว่าคุณจะบันทึกการกดแป้นจำนวนมากได้
Chris Conway

6
นอกจากนี้แทนที่จะเป็น Cx b คุณสามารถกด Cx k เพื่อกลับสู่บัฟเฟอร์เดิมได้
ยู

32
C-x C-jจะไม่ผูกพันตามค่าเริ่มต้นสำหรับฉัน การทำM-x load-library RET dired-x RETก่อนทำให้มันถูกผูกไว้
ntc2

4
ทางเลือกอื่นหากC-x C-jไม่ถูกผูกไว้จะทำM-x dired-jumpในครั้งแรก มันจะโหลดโดยอัตโนมัติdired-x(ซึ่งจะทำให้C-x C-jถูกกำหนดจากจุดนี้เป็นต้นไป)
เฟอร์นันโดบาสโซ

120

เพื่อความสมบูรณ์เนื่องจากบางคนอาจไปที่หน้านี้โดยคิดว่าพวกเขาจะได้รับคำตอบสำหรับคุณสมบัติ "บันทึกเป็น" ของ Emacs นั่นคือ Cx Cw สำหรับไฟล์ที่เปิดอยู่


Cx Cw หรือใช้เมนูFile > Save as...
ยู

ไม่ใช่ "บันทึกเป็น" เนื่องจากไฟล์ที่คุณแก้ไขจะยังคงเป็นไฟล์ดั้งเดิม
asmeurer

11
@ ผู้ตรวจสอบคุณผิด! หลังจากบันทึกแล้วคุณจะแก้ไขไฟล์ใหม่
Joel G Mathew

3
อีกครั้งทำไมไม่มีคุณสมบัติในการโหวตความคิดเห็น?
แฟน

7
อาจหมายความว่า asmeurer "ไฟล์ที่คุณ [เคย] แก้ไขจะยังคงมีอยู่ ["] ถ้าเช่นนั้นถูกต้องหรือไม่ ฉันจะตรวจสอบ แต่แล้วคุณไม่สามารถลงคะแนนความคิดเห็นของฉันได้ฮ่าฮ่าฮ่า
เบรดี้ Trainor

25

สิ่งที่ฉันชอบคือหนึ่งจาก Magnars (ของหิน emacs 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 สำหรับรุ่นที่ถูกต้อง


สิ่งนี้ไม่ทำงานอย่างถูกต้อง อันนี้เพิ่ม "/" ในตอนท้ายของไฟล์
mythicalcoder

2
ขอบคุณที่โพสต์ข้อความนี้ให้ฉัน วิธี SO คือการแก้ไขคำตอบไม่ใช่โพสต์ใหม่แก้ไขเล็กน้อย
Cat Unfun

15

นี่คือเวอร์ชันที่แข็งแกร่งกว่าที่ดัดแปลงมาจากสตีวี

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

ทำได้ดีนี่. ตอนนี้เย็นในฉัน function.el
เฟลิกซ์ดี.

11

นี่เป็นอีกเวอร์ชั่นหนึ่งที่ค่อนข้างแข็งแกร่งและทราบว่า 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)))))))

คุณสามารถอ่านเพิ่มเติมได้ที่นี่


7

หากคุณกำลังใช้Spacemacsแล้วคุณจะได้รับพฤติกรรมนี้ได้ฟรีตั้งแต่มันมาพร้อมกับการดำเนินงานของrename-current-buffer-file(ขึ้นอยู่กับ magnars) SPC-f-Rที่เริ่มต้นผูกไว้กับ

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


4

มีวิธีที่ง่ายมากคุณกดคำสั่งMxและพิมพ์vc-rename-fileหลังจากนั้นคุณเพียงแค่เลือกไฟล์ปัจจุบันที่ไดเรกทอรีและเลือกชื่อใหม่ บัฟที่มีไฟล์ที่เปลี่ยนแปลงจะถูกรีเฟรช

ที่มา: https://www.gnu.org/software/emacs/manual/html_node/emacs/VC-Delete_002fRename.html


1
สิ่งนี้มีผลข้างเคียง (ไม่ต้องการ) ของการเพิ่มไฟล์เก่าและใหม่ที่จะส่งไปยังการควบคุมเวอร์ชัน แต่ +1 เพราะมันใช้ฟังก์ชั่นบิวอิน (ส่วนใหญ่) ตอบคำถามของ OP
ไดโนเสาร์

3

ขึ้นอยู่กับรุ่น 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)))))))

อันนี้ดีกว่า รุ่น magnars ที่ระบุไว้ด้านบนไม่ทำงานอย่างถูกต้อง เพิ่มอักขระ "/" ที่ส่วนท้าย
mythicalcoder

-1

มันสามารถทำได้โดยการคัดลอก Shift + c ในไฟล์และ emacs จะขอให้คุณแสดงชื่อของพา ธ รวมถึงชื่อไฟล์ดังนั้นคุณเพียงแค่ให้ชื่อใหม่และป้อน ... แน่นอนคุณต้องลบชื่อเดิม


1
ดูเหมือนว่าคุณกำลังอ้างถึง "C" ในโหมด dired? นั่นเป็นการคัดลอกไฟล์ไม่ใช่การเปลี่ยนชื่อไฟล์ซึ่ง (ตามที่ @ChrisConway จดบันทึกไว้) ใน dired เสร็จสิ้นด้วย "R" และนอกจากนี้ OP ขอเปลี่ยนชื่อบัฟเฟอร์ปัจจุบัน
ลิ้มรส Cubranic
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.