Como renomear um arquivo aberto no Emacs?


237

Existe uma maneira de renomear um arquivo aberto no Emacs? Enquanto eu estou vendo? Algo como salvar como, mas o original deve desaparecer.

Respostas:


88

Tente esta função no arquivo .emacs de Steve Yegge :

;; fonte: http://steve.yegge.googlepages.com/my-dot-emacs-file
(renomear arquivo-renomear-e-buffer (novo nome)
  "Renomeia o buffer atual e o arquivo que está visitando para NEW-NAME."
  (interativo "sNew name:")
  (let ((nome (nome do buffer)))
        (nome do arquivo (nome do arquivo-buffer)))
    (se (não o nome do arquivo)
        (mensagem "Buffer '% s' não está visitando um arquivo!" nome)
      (if (get-buffer new-name)
          (mensagem "Um buffer denominado '% s' já existe!" new-name)
        (progn
          (renomeie o arquivo nome do arquivo novo nome 1)
          (renomear-buffer novo nome)
          (nome do arquivo visitado-conjunto nome-novo)
          (conjunto-tampão-modificado-p nil))))))

Dê uma olhada nessa página, há outra função relacionada realmente útil, chamada "move-buffer-file".


1
Nota: este método não é compatível com o (setq uniquify-buffer-name-style 'forward)significado se você tiver um buffer nomeado users\index.html(porque você já possui outro buffer para posts\index.html) a renomeação falhará
— dolzenko

(set-buffer-modified-p nil)parece desnecessário. Se você chamasse rename-file-and-bufferum buffer modificado e tentasse matá-lo, ele o faria feliz sem avisar sobre alterações não salvas.
— Rdugin

Essa função também solicita (um pouco irritante) um novo nome antes de verificar se o buffer atual está associado a um arquivo (nesse caso, ele é abortado).
— Thomas

338

Sim, com o diredmodo, você pode:

  • C-x d abrir dired
  • RET para selecionar o diretório do arquivo atual
  • C-x C-j( dired-jumppara o nome do arquivo atual, em Dired)
  • Rrenomear o arquivo (ou dired-do-rename).
  • q para voltar ao buffer de arquivo (renomeado)

A renomeação é equivalente a um shell mv, mas também atualiza os buffers abertos e, ao contrário mv, não altera os tempos de acesso e modificação no arquivo no sistema de arquivos.


9
Isso não está renomeando diretamente o arquivo atual.
— pupeno

4
Cx be você está de volta no buffer original. Você pode escrever uma função Elisp para fazer isso, mas duvido que você salve muitas teclas pressionadas com ela.
— Chris Conway

6
Além disso, em vez de Cx b, você pode pressionar Cx k para voltar ao buffer original.
— Yoo

32
O C-x C-jnão está vinculado por padrão para mim. Fazer M-x load-library RET dired-x RETprimeiro o torna vinculado.
— Ntc2 31/10/2013

4
Outra alternativa, se C-x C-jnão estiver ligada, é apenas fazer M-x dired-jumpna primeira vez. Ele será carregado automaticamente dired-x(o que também fará C-x C-jcom que seja definido a partir deste ponto).
— Fernando Basso

120

Apenas para completar, já que algumas pessoas podem visitar esta página pensando que receberão uma resposta para o recurso "salvar como" do Emacs, que é o Cx Cw para um arquivo aberto.


Cx Cw ou use o menuFile > Save as...
— Yoo

Não é "salvar como", pois o arquivo que você está editando ainda será o original.
— asmeurer

11
@asmeurer Você está errado! Após salvar, você estará editando o novo arquivo.
— Joel G Mathew

3
Mais uma vez, por que não há um recurso para votar com desconfiança ?!
— bearfriend

7
Talvez como memeurer quis dizer, "o arquivo que você estava editando ainda existirá". Então, isso está correto? Eu verificaria, mas então, você não pode rebater meu comentário, hahaha.
— Brady Trainor

25

O meu favorito é o de Magnars (da fama dos screencasts de rochas do emacs ).

Ao contrário das outras alternativas, você não precisa digitar o nome do zero - é necessário modificar o nome atual.

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

Obrigado a James Yang pela versão correta.


Isso NÃO está funcionando corretamente. Este adiciona um "/" no final do arquivo.
— mythicalcoder

2
Obrigado por postar isso para mim. A maneira SO é corrigir as respostas, não publicar novas e ligeiramente modificadas.
— The Unfun Cat

15

Aqui está uma versão mais robusta adaptada de 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))

Agradável. Agora relaxando em minhas funções.el.
— Felix D.

11

Aqui está outra versão, bastante robusta e com conhecimento de 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)))))))

Você pode ler mais sobre isso aqui .



4

Existe uma maneira muito fácil: você pressiona o comando Mx e , em seguida, digite vc-rename-file , depois basta selecionar o arquivo atual no diretório e escolher o novo nome. O buff que possui o arquivo alterado será atualizado.

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


1
Isso tem o efeito colateral (não necessariamente desejável) de adicionar os arquivos antigos e novos a serem confirmados no controle de versão. Mas +1 porque usa uma função interna para (principalmente) responder à pergunta do OP.
— dinossauro

3

com base na versão magnars, modifiquei como abaixo, corrigi a parte do nome do arquivo 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)))))))

Este é melhor. A versão dos magnares fornecida acima NÃO está funcionando corretamente. Adicione um caractere "/" no final
— mythicalcoder

-1

Pode ser conseguido por cópia. shift + c no arquivo e o emacs solicitará que você indique um nome para o caminho, incluindo o nome do arquivo, para que você apenas forneça o novo nome e insira ... é claro, você deve excluir o antigo.


1
Você parece estar se referindo a "C" no modo direcionado? Isso é copiar o arquivo, não renomeá-lo, o que (como @ChrisConway observou) em dired é feito com "R". Além disso, o OP pediu uma renomeação do buffer atual.
— Davor Cubranic
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.