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.

pupeno
quelle

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.

Matt Curtis
quelle
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.

Chris Conway
quelle
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.

Jim G.
quelle
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.

Die Unfun Cat
quelle
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))
Shawn Hoover
quelle
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 .

Bozhidar Batsov
quelle
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

Rafael Nascimento
quelle
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)))))))
James Yang
quelle
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.

Eric_Chen
quelle
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