12

How can I insert the file name of the active file buffer into a command?

When I invoke a command that needs a file name, I am often doing so from a file buffer and want the name of that file while typing the command into the minibuffer.

I'm looking for a hypothetical C-x that I can type during forming a command line in the minibuffer.

So if, while the current buffer is a file named Lorem Ipsum.txt, I type this:

M-x grep RET 'foo' SPC C-x … RET

the M-xgrepRET presents a minibuffer prompting for the grep command. In response, I've typed the regex pattern argument ('foo') and inserted the filename argument (C-x). That minibuffer will end up as:

grep -nH -e 'foo' 'Lorem Ipsum.txt'

What existing command gets the current file buffer's file name like this? What is its default key binding?

  • 3
    I'm surprised nobody's mentioned M-n. It doesn't work everywhere, but works in a lot of places. Also, since you're grepping, you might like lgrep and rgrep, which are a little more interactive, I think. – Malabarba Sep 9 '15 at 9:46
17

What existing command gets the current file buffer's file name like this?

Unfortunately there is no ready made command for this, but we can make one as follows:

(defun name-of-the-file ()
  "Gets the name of the file the current buffer is based on."
  (interactive)
  (insert (buffer-file-name (window-buffer (minibuffer-selected-window)))))

The magic is in the minibuffer-selected-window function; it does the right thing by picking the last buffer before the minibuffer was activated. Otherwise using just the buffer-file-name won't get us the filename into the minibuffer. Interestingly, the same function can be used in a regular buffer or minibuffer to insert the file name. No special treatment is needed.

What is its default key binding?

There is none, but you can pick a convenient one and assign it as follows:

(global-set-key (kbd "C-c f") 'name-of-the-file)

Put the above lisp code lines in your init.el file.

This works in most trivial cases, but hard to predict what conflicts it might have with whatever modes you have active when invoking this function.

What if the buffer is not visiting a valid filename, such as the scratch buffer? Then this error is shown in the echo area:

name-of-the-file: Wrong type argument: char-or-string-p, nil

Picking a valid buffer with a proper filename before invoking the shortcut will avoid such errors.

There are several other solutions like the above, but they mainly differ in how they handle exceptions or overrides for any conflicts. For example, some employ mode-hooks to make this function available only in certain modes.

  • For this to work I think one must enable-recursive-minibuffers. – Dieter.Wilhelm Sep 8 '15 at 6:39
  • If the command is only supposed to be used in the minibuffer, the following binding may be used instead (define-key minibuffer-local-map (kbd "C-c f") 'name-of-the-file)'. In addition to this useful function I also created the function name-of-the-buffer` which I bound to C-c b that inserts the current buffer name. – Dov Grobgeld Jun 4 '17 at 8:11
2

When using dired-x the keyboard shortcut C-x C-j is bound to dired-jump. So from your file buffer you end up at the right dired line and can copy its file name with w. And then you are able to paste it in the mini buffer.

Another possibility to aleviate typing of the file name is the standard Emacs mini buffer file completion. Just typing the first characters of your filename and then TAB.

  • 1
    You can copy the name of the file on the current Dired line just by using w (command dired-copy-filename-as-kill). – Drew Apr 15 '17 at 5:36
-1

The question asks for an existing Emacs command to do this.

As stated earlier:

Unfortunately there is no ready made command for this

which turns out to be the answer to this question.

  • There are ways to alleviate your use case and others suggested bespoke coding solutions, so I think your statement is not right. You didn't ask specifically for an out-of-the-box Emacs' way! – Dieter.Wilhelm Nov 1 '16 at 6:35
  • I asked specifically for an existing command for the purpose, so yes this answer is correct. – bignose Nov 3 '16 at 4:52

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.