Come rinominare un file aperto in Emacs?


237

C'è un modo per rinominare un file aperto in Emacs? Mentre lo sto visualizzando? Qualcosa di simile a save-as, ma quello originale dovrebbe andare via.

Risposte:


88

Prova questa funzione dai .emacs di Steve Yegge :

;; fonte: http://steve.yegge.googlepages.com/my-dot-emacs-file
(defunenome-file-e-buffer rinominare (nuovo-nome)
  "Rinomina sia il buffer corrente sia il file che sta visitando NEW-NAME."
  (interattivo "sNew name:")
  (let ((name (buffer-name))
        (nome file (nome file buffer)))
    (if (non nome file)
        (messaggio "Buffer '% s' non sta visitando un file!")
      (if (get-buffer new-name)
          (messaggio "Un buffer chiamato '% s' esiste già!" new-name)
        (progn
          (rinomina file nome nuovo nome 1)
          (rinomina buffer nuovo nome)
          (set-visitato-nome-file-nome-nuovo)
          (set-buffer-modificato-p nil))))))

Dai un'occhiata a quella pagina, c'è un'altra funzione correlata davvero utile lì, chiamata "move-buffer-file".


1
Nota: questo metodo non è compatibile con il (setq uniquify-buffer-name-style 'forward)significato se si dispone di un buffer denominato users\index.html(poiché si dispone già di un altro buffer per posts\index.html) la ridenominazione non riuscirà
dolzenko,

(set-buffer-modified-p nil)sembra inutile. Se avessi richiamato rename-file-and-bufferun buffer modificato e avessi tentato di eliminarlo, lo farebbe felicemente senza avvisarti delle modifiche non salvate.
Roldugin,

Questa funzione ti chiederà (in modo un po 'fastidioso) un nuovo nome prima di verificare se il buffer corrente è associato a un file (nel qual caso si interrompe).
Thomas,

338

Sì, con la diredmodalità puoi:

  • C-x d per aprire diretto
  • RET per selezionare la directory del file corrente
  • C-x C-j( dired-jumpal nome del file corrente, in Dired)
  • Rper rinominare il file (o dired-do-rename).
  • q per tornare al buffer di file (rinominato)

La ridenominazione equivale a una shell mv, ma aggiornerà anche eventuali buffer aperti e, diversamente da mvciò, non cambierà l'accesso e i tempi di modifica sul file nel filesystem.


9
Questo non sta rinominando direttamente il file corrente.
pupeno,

4
Cx b e sei tornato nel buffer originale. Potresti scrivere una funzione Elisp per farlo, ma dubito che risparmierai molti tasti con esso.
Chris Conway,

6
Inoltre, anziché Cx b, è possibile premere Cx k per tornare nel buffer originale.
Yoo

32
Non C-x C-jè vincolato per impostazione predefinita per me. Fare M-x load-library RET dired-x RETprima lo rende vincolato.
ntc2,

4
Un'altra alternativa se C-x C-jnon è associata è M-x dired-jumpla prima volta. Si caricherà automaticamente dired-x(il che farà sì C-x C-jche sia definito da questo punto in poi).
Fernando Basso,

120

Solo per completezza, poiché alcune persone potrebbero visitare questa pagina pensando di ottenere una risposta per la funzione "salva con nome" di Emacs, questo è Cx Cw per un file aperto.


Cx Cw o usa il menuFile > Save as...
Yoo

Non abbastanza "salva con nome", poiché il file che stai modificando sarà comunque quello originale.
asmeurer,

11
@asmeurer Ti sbagli! Dopo il salvataggio, modificherai il nuovo file.
Joel G Mathew,

3
Ancora una volta, perché non esiste una funzione per il downgrade dei commenti ?!
Bearfriend

7
Forse asmeurer voleva dire "il file che [stavi] modificando continuerà [esisterà]". Allora, è corretto? Vorrei controllare, ma poi non puoi sottovalutare il mio commento, ahahah.
Brady Trainor,

25

Il mio preferito è quello di Magnars (di fama di screencast .)

A differenza delle altre alternative, non è necessario digitare il nome da zero: si ottiene il nome corrente da modificare.

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

Grazie a James Yang per una versione corretta.


Questo NON funziona correttamente. Questo aggiunge un "/" alla fine del file.
miticalcoder

2
Grazie per avermelo pubblicato. Il modo SO è quello di correggere le risposte, non pubblicare nuove, leggermente modificate.
The Unfun Cat,

15

Ecco una versione più robusta adattata da 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))

Ben fatto. Ora mi rilasso nelle mie funzioni.el.
Felix D.

11

Ecco un'altra versione, abbastanza robusta e consapevole di 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)))))))

Puoi leggere di più qui .



4

C'è un modo molto semplice, premi il comando Mx e poi digita vc-rename-file , dopodiché devi solo selezionare il tuo file corrente nella directory e scegliere il nuovo nome. Il buff che ha il file modificato verrà aggiornato.

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


1
Questo ha l'effetto collaterale (non necessariamente desiderabile) di aggiungere i file vecchi e nuovi da impegnare nel controllo della versione. Ma +1 perché usa una funzione integrata per (principalmente) rispondere alla domanda del PO.
dinosauro,

3

in base alla versione dei magnari, ho modificato come di seguito, risolto il nome del file 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)))))))

Questo è migliore. La versione dei magnari sopra indicata NON funziona correttamente. Aggiungi un carattere "/" alla fine
mythicalcoder

-1

Può essere ottenuto tramite copia. shift + c sul file ed emacs ti chiederà di indicare un nome per il percorso incluso il nome del file, quindi devi solo fornire il nuovo nome e inserire ... ovviamente, devi eliminare quello precedente.


1
Sembra che ti riferisca a "C" in modalità Dired? Questo è copiare il file, non rinominarlo, che (come notato da @ChrisConway) in dired è fatto con "R". Inoltre, OP ha chiesto una ridenominazione del buffer corrente.
Davor Cubranic
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.