4

How can I close all unmodified buffers?

Usually after a day of work - I've got a ton of buffers / frames open. Right now I have to navigate to each frame and close it - which then prompts me if the file has been modified.

  • Which frames do you want to close exactly? Is it frames all of whose windows show unmodified buffers? – Omar Dec 14 '17 at 3:27
10

One way would be to use ibuffer:

  1. Open ibuffer (I have it bound to a key, but M-x ibuffer will work.)
  2. Mark all modified buffers: * m
  3. Toggle the marks, so that unmodified buffers are marked instead: t
  4. Kill the marked buffers: D

For frames, you can use delete-other-frames (C-x 5 1).

If you do this often you may want to define your own command. Here's a starting point:

(defun my-clean-frames-and-buffers ()
  "Kills all unmodified buffers and closes all but the selected frame."
  (interactive)
  (save-window-excursion
    (dolist (buffer (buffer-list))
      (and (buffer-live-p buffer)
           (not (buffer-modified-p buffer))
           (kill-buffer buffer))))
  (delete-other-frames))

This won't prompt you and might kill more than you want, so some tweaking might be required.

  • Although this seems to work for buffers alone, this does not seem to close related frames. So I'm still faced with having to navigate to each frame and close it. – Chris Stryczynski Dec 7 '17 at 10:40
  • 3
    Common frame commands are all on the C-x 5 prefix, which we can inspect with C-x 5 C-h, which shows us that C-x 5 1 deletes all frames other than the current one (which is easy to remember, as it's the analog of what C-x 1 does to windows). – phils Dec 7 '17 at 12:06
0

There are two parts to your question:

  1. Kill all unmodified buffers.

  2. Delete their frames.

For #2, do you really mean frames? In Emacs, a "frame" is a window-manager window, and an (Emacs) "window" is a pane of an Emacs frame (a frame shows one or more windows). Do you really want to delete a frame that might be showing an unmodified buffer in one of its windows?

I'm guessing that you instead want to delete all Emacs windows showing unmodified buffers, at the same time that you kill those buffers.


For #2:

If you use library misc-cmds.el then you can use command (function) kill-buffer-and-its-windows. It kills a buffer and deletes all windows showing it (on whatever frames).

This is automatically used by the solution for #1, below, provided you have library misc-cmds.el in your load-path, so it can be required.

For #1:

If you use Icicles then C-x k is bound by default (in icicle-mode) to multi-command icicle-kill-buffer.

All you need to do is use C-x k, followed by C-x * -, followed by C-!. That kills all of the unmodified buffers and deletes all of their windows.

If you want to see which buffers are being acted on you can use TAB anytime after C-x k. For example, C-x k TAB shows you the names of all buffers, and C-x k C-x * - TAB shows you the names of all buffers that are modified (and only those buffers).

C-! acts on all of the completion candidates. In this case, the candidates are buffer names, and after you use C-x * - the candidates are only the unmodified buffers. The action is kill-buffer, so all of the unmodified buffers are killed.

A multi-command is an Icicles command that lets you act on multiple completion candidates (and on the same candidate multiple times) within the same invocation of the command. C-! always performs the command action on all of the current completion candidates.

In this case, you just needed to filter the buffer-name candidates to remove those for modified buffers, before hitting C-! to kill the rest.

Yes, it's not obvious here that C-x * - filters out the modified buffers. But C-h k C-x k tells you about this. (Actually, it refers you to the doc for icicle-buffer, which provides a pretty complete description of all Icicles multi-commands that read a buffer name.) The more complete doc for this is here: Icicle - Buffer-Name Input.


icicle-kill-buffer (C-x k), like icicle-buffer (C-x b) is not only a multi-commmand. In addition, completion candidates are in fact multi-completions, with two parts. Each of your inputs can have two patterns, which match those parts:

  1. Buffer-name pattern
  2. Buffer-content pattern

If you just type some text, that matches the buffer name. To then match also the buffer content, you use C-M-j and then type the content-matching pattern. (If you want to match only content and not also names, then just start with C-M-j at the prompt.)

So for example, you could kill all unmodified buffers that contain text that matches the regexp foo.*bar.*toto:

C-x k S-TAB -- Show all buffers

C-x * - -- Remove modified buffers as candidates

C-M-j -- Don't bother to match buffer names

foo.*bar.*toto -- Match buffer content (removing names of buffers that don't match)

C-! -- Kill the remaining buffers, which are unmodified and have text that matches foo.*bar.*toto

In Icicles completion, S-TAB performs apropos completion, which does regexp matching.


If you really did mean that you want to delete the frames and not just the windows showing unmodified buffers, then library frame-cmds.el can help. It advises function delete-window so that the frame showing the window to be deleted is also deleted, provided that it its sole window. This is the advice:

(defadvice delete-window (around delete-frame-if-one-win activate)
  "If WINDOW is the only one in its frame, then `delete-frame' too."
  (with-selected-window
      (or (ad-get-arg 0)  (selected-window))
    (if (one-window-p t) (delete-frame) ad-do-it)))

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.