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.