Wie benenne ich eine geöffnete Datei in Emacs um?


237

Gibt es eine Möglichkeit, eine geöffnete Datei in Emacs umzubenennen? Während ich es mir ansehe? So etwas wie Speichern unter, aber das Original sollte verschwinden.

Antworten:


88

Probieren Sie diese Funktion aus Steve Yegges .emacs aus :

;; Quelle: http://steve.yegge.googlepages.com/my-dot-emacs-file
(Defun Rename-Datei-und-Puffer (neuer Name)
  "Benennt sowohl den aktuellen Puffer als auch die Datei, die er besucht, in NEW-NAME um."
  (interaktiver "neuer Name:")
  (let ((name (puffername))
        (Dateiname (Puffer-Dateiname))
    (if (nicht Dateiname)
        (Meldung "Buffer '% s' besucht keine Datei!" Name)
      (if (get-buffer new-name)
          (Meldung "Ein Puffer mit dem Namen '% s' existiert bereits!" Neuer Name)
        (Prognose
          (Datei umbenennen Dateiname neuer Name 1)
          (Umbenennungspuffer neuer Name)
          (Set-Visited-File-Name New-Name)
          (set-buffer-modifiziert-p nil))))))

Schauen Sie sich diese Seite an, dort gibt es eine weitere wirklich nützliche Funktion, die "move-buffer-file" heißt.


1
Hinweis: Diese Methode ist nicht mit der (setq uniquify-buffer-name-style 'forward)Bedeutung kompatibel , wenn Sie einen Puffer namens users\index.html(weil Sie bereits einen anderen Puffer für haben posts\index.html) haben,
schlägt

(set-buffer-modified-p nil)scheint unnötig. Wenn Sie rename-file-and-buffereinen geänderten Puffer aufrufen und dann versuchen, ihn zu beenden, würde er dies gerne tun, ohne Sie vor nicht gespeicherten Änderungen zu warnen.
Roldugin

Diese Funktion fragt Sie auch (etwas ärgerlich) nach einem neuen Namen, bevor Sie prüfen, ob der aktuelle Puffer überhaupt einer Datei zugeordnet ist (in diesem Fall wird er abgebrochen).
Thomas

338

Ja, im diredModus können Sie:

  • C-x d dired öffnen
  • RET um das Verzeichnis der aktuellen Datei auszuwählen
  • C-x C-j( dired-jumpzum Namen der aktuellen Datei in Dired)
  • Rum die Datei (oder dired-do-rename) umzubenennen .
  • q um zum (umbenannten) Dateipuffer zurückzukehren

Das Umbenennen entspricht einer Shell mv, aktualisiert jedoch auch alle geöffneten Puffer und mvändert im Gegensatz dazu nicht den Zugriff und die Änderungszeiten für die Datei im Dateisystem.


9
Dadurch wird die aktuelle Datei nicht direkt umbenannt.
Pupeno

4
Cx b und du bist wieder im ursprünglichen Puffer. Sie könnten eine Elisp-Funktion schreiben, um dies zu tun, aber ich bezweifle, dass Sie damit viele Tastenanschläge sparen werden.
Chris Conway

6
Anstelle von Cx b können Sie auch Cx k drücken, um wieder im ursprünglichen Puffer zu sein.
Yoo

32
Das C-x C-jist für mich nicht standardmäßig gebunden. Das M-x load-library RET dired-x RETerste zu tun macht es gebunden.
ntc2

4
Eine andere Alternative, wenn sie C-x C-jungebunden ist, ist nur M-x dired-jumpbeim ersten Mal. Es wird automatisch geladen dired-x(was auch dazu führt C-x C-j, dass es ab diesem Zeitpunkt definiert wird).
Fernando Basso

120

Der Vollständigkeit halber, da einige Leute diese Seite besuchen und glauben, sie würden eine Antwort auf die Funktion "Speichern unter" von Emacs erhalten, ist dies Cx Cw für eine geöffnete Datei.


Cx Cw oder benutze das MenüFile > Save as...
Yoo

Nicht ganz "Speichern unter", da die Datei, die Sie bearbeiten, immer noch die Originaldatei ist.
Asmeurer

11
@asmeurer Du liegst falsch! Nach dem Speichern bearbeiten Sie die neue Datei.
Joel G Mathew

3
Warum gibt es keine Funktion zum Herunterstimmen von Kommentaren?!
Bärenfreund

7
Vielleicht meinte asmeurer, "die Datei, die Sie bearbeitet haben, wird noch existieren". Ist das dann richtig? Ich würde es überprüfen, aber dann können Sie meinen Kommentar nicht ablehnen, hahaha.
Brady Trainor

25

Mein Favorit ist der von Magnars (von Emacs Rocks Screencasts Ruhm.)

Im Gegensatz zu den anderen Alternativen müssen Sie den Namen nicht von Grund auf neu eingeben - Sie erhalten den aktuellen Namen zum Ändern.

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

Vielen Dank an James Yang für eine korrekte Version.


Dies funktioniert NICHT richtig. Dieser fügt am Ende der Datei ein "/" hinzu.
Mythicalcoder

2
Danke, dass du das für mich veröffentlicht hast. Die SO-Methode besteht darin, Antworten zu korrigieren und keine neuen, leicht modifizierten zu veröffentlichen.
Die Unfun Cat

15

Hier ist eine robustere Version von 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))

Schön. Jetzt in meinen Funktionen chillen.
Felix D.

11

Hier ist eine andere Version, die ziemlich robust und VC-fähig ist:

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

Sie können mehr darüber lesen Sie hier .



4

Es gibt eine sehr einfache Möglichkeit, Sie drücken den Befehl Mx und geben dann vc-rename-file ein. Danach müssen Sie nur noch Ihre aktuelle Datei im Verzeichnis auswählen und dann den neuen Namen auswählen. Der Buff mit der geänderten Datei wird aktualisiert.

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


1
Dies hat den (nicht unbedingt wünschenswerten) Nebeneffekt, dass die alten und neuen Dateien, die in die Versionskontrolle übernommen werden sollen, hinzugefügt werden. Aber +1, weil es eine eingebaute Funktion verwendet, um (meistens) die Frage des OP zu beantworten.
Dinosaurier

3

basierend auf der Magnar-Version, die ich wie folgt modifiziert habe, wurde der INIT-Dateinamen-Teil korrigiert:

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

Dieses hier ist besser. Die oben angegebene Magnar-Version funktioniert NICHT ordnungsgemäß. Fügen Sie am Ende ein "/" hinzu
mythicalcoder

-1

Dies kann durch Kopieren erreicht werden. Shift + C in der Datei und Emacs werden Sie auffordern, einen Namen für den Pfad einschließlich des Dateinamens anzugeben. Geben Sie also einfach den neuen Namen ein und geben Sie ein ... natürlich müssen Sie den vorherigen löschen.


1
Sie scheinen sich im Dired-Modus auf "C" zu beziehen? Das heißt, die Datei wird kopiert, nicht umbenannt, was (wie @ChrisConway feststellte) in dired mit "R" erfolgt. Außerdem bat OP um eine Umbenennung des aktuellen Puffers.
Davor Cubranic
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.