ChatGPT解决这个技术问题 Extra ChatGPT

The function to show current file's full path in mini buffer

I need to get the full path of the file that I'm editing with emacs.

Is there a function for that?

If not, what would be the elisp function for getting that?

How can I copy the result (path name) to a clipboard so that I can reuse it?

I'm using Mac OS X and Aqumacs.

(setq filepath (get-fullpath-current-file)) ???
(copy-to-clipboard 'filepath) ???

ADDED

(defun show-file-name ()
  "Show the full path file name in the minibuffer."
  (interactive)
  (message (buffer-file-name))
  (kill-new (file-truename buffer-file-name))
)
(global-set-key "\C-cz" 'show-file-name)

Combining the two answers that I got, I could get what I want. Thanks for the answers. And some more questions.

What's for (file-truename)?

Can I copy the path name to System(OS)'s clipboard, not the kill ring so that I can use the info with the other apps?

did you try C-x C-f ? It's not meant for that but it works (meant for this gnu.org/software/emacs/manual/html_node/emacs/Visiting.html)

A
APerson

It's the built-in function buffer-file-name that gives you the full path of your file.

The best thing to do is to have your emacs window to always show your system-name and the full path of the buffer you're currently editing :

(setq frame-title-format
      (list (format "%s %%S: %%j " (system-name))
        '(buffer-file-name "%f" (dired-directory dired-directory "%b"))))

You can also do something like this :

(defun show-file-name ()
  "Show the full path file name in the minibuffer."
  (interactive)
  (message (buffer-file-name)))

(global-set-key [C-f1] 'show-file-name) ; Or any other key you want

In emacs 24 buffer-file-name is a variable
...but also still a function
If it's a function then why doesn't it appear in M-x?
asmeurer - because it's not interactive
@Talespin_Kit Yes, absolutely. Elisp is a "lisp-2" as opposed to a "lisp-1", meaning there are two independent name-spaces (variables and functions). Each symbol therefore has a "function slot" and a "value slot", and which slot is accessed depends on the context. There are many examples in practice (e.g. any minor mode name will be both a function and a variable). This is also why you need to use the likes of funcall to call a function that is stored as the value of a variable foo, because if you used (foo) you would be using the function slot of foo rather than the value slot.
a
asmeurer

To borrow from Jérôme Radix's answer, if you just want to quickly see the file path of the current buffer, you can do M-: buffer-file-name.

Alternately, type (buffer-file-name) in the buffer somewhere and run C-x C-e on the closing parenthesis (this will work in any mode, not just lisp-mode).


Thanks, I thought the buffer-file-name as a function, but it does not appear in M-x, but appears in M-: as emacs eval, there I can run the command, thanks to your answer :)
Yeah, M-x only runs interactive functions, whereas M-: runs any elisp function.
C-h v and enter buffer-file-name gives you the value and description of the variable with the benefit of tab completion.
J
Julien Palard

My trick is to do a C-x C-f like to open a file, it wil prefill the minibuff with the current file path, C-g to quit. Faster than M-: buffer-file-name but far far uglier than any other methods.


I do this too. It's not as hardcore emacs-y but if all I care about is the path to the current file, it works.
If you open a file, say A, and then jump to another file, say B, e.g. using some jump to definition functionality of a plugin, this method shows the path of A, not B! Thus, this answer does not always offer what the OP is asking for.
C-x C-v will show you not just the current path but the current file's name as well
@kuzzooroo that's right for non ido-mode users (The name is displayed in C-x C-f with you use ido-mode).
T
Trey Jackson

The direct implementation of what you want is:

(defun copy-full-path-to-kill-ring ()
  "copy buffer's full path to kill ring"
  (interactive)
  (when buffer-file-name
    (kill-new (file-truename buffer-file-name))))

That said, I find it incredibly useful to be able to get the full path of what is in the minibuffer, and this is what I use:

(define-key minibuffer-local-completion-map "\C-r" 'resolve-sym-link)
(defun resolve-sym-link ()
  "Try to resolve symbolic links into true paths."
  (interactive)
  (beginning-of-line)
  (let* ((file (buffer-substring (point)
                                 (save-excursion (end-of-line) (point))))
         (file-dir (file-name-directory file))
         (file-true-dir (file-truename file-dir))
         (file-name (file-name-nondirectory file)))
    (delete-region (point) (save-excursion (end-of-line) (point)))
    (insert (concat file-true-dir file-name))))

And then if I want it in the clipboard, I just kill the line (C-a C-k). But we could easily copy the truename to the clipboard in the above command, just change the last line to be:

(insert (kill-new (concat file-true-dir file-name)))))

The new part is the call to 'kill-new which puts the string in the kill ring.


Can you elaborate how to use this settings? And what does "\C-r" means?
Never mind. I figured it out. I think it is useful when I am in ido mode and pointing to a file, then I just press C-r to get the full path of that file. Indeed useful. However I still don't know why use \C instead of C.
t
thanhpk

No need for extra function, just

M-! pwd

While this can work, it won't work on Windows systems, and it fails to account for the fact that emacs' current working directory can be different from the directory of the current buffer's file. You can see this for yourself by visiting a file with C-x C-f, running M-! pwd, then M-x cd and selecting a different directory, then running M-! pwd again.
T
Tobias

I have the following code already in use for a long time. It copies the full file path to the kill ring when I press the middle mouse button on the buffer name in the mode-line. It copies just the buffer name to the kill-ring when I press shift-mouse-2 on the buffer-name in the mode-line.

(defun copy-buffer-file-name (event &optional bufName)
  "Copy buffer file name to kill ring.
If no file is associated with buffer just get buffer name.
"
  (interactive "eP")
  (save-selected-window
    (message "bufName: %S" bufName)
    (select-window (posn-window (event-start event)))
    (let ((name (or (unless bufName (buffer-file-name)) (buffer-name))))
      (message "Saved file name \"%s\" in killring." name)
      (kill-new name)
      name)))

(define-key mode-line-buffer-identification-keymap [mode-line mouse-2] 'copy-buffer-file-name)
(define-key mode-line-buffer-identification-keymap [mode-line S-mouse-2] '(lambda (e) (interactive "e") (copy-buffer-file-name e 't)))

D
David

C-x C-b shows a list of buffers and the file path for each buffer where applicable.


M
MLev

C-x C-d, also callable via M-x list-directory, will show you the directory for your current file, and you only need to hit the "Enter" key to clear the minibuffer. Additional details are available here.


my favorite answer, simple, quick and easy!
m
memeplex

C-u C-x C-b lists buffers currently visiting files.


y
yPhil

To do what the title says (show the current file path in the minibuffer) you can do this:

M-x buffer-file-name

To permanently show it in the mode-line, you can use this:

(setq-default mode-line-buffer-identification
              (list 'buffer-file-name
                    (propertized-buffer-identification "%12f")
                    (propertized-buffer-identification "%12b")))

Or this (color + abbrev) :

(setq-default mode-line-buffer-identification
              '((:eval
                 (list (propertize (abbreviate-file-name
                                    (expand-file-name buffer-file-name))
                                   'face 'font-lock-string-face)))))

B
Barry Kelly

Can I copy the path name to System(OS)'s clipboard, not the kill ring so that I can use the info with the other apps?

You can if you shell out to something like xclip (Linux), pbcopy (Mac), putclip (Cygwin).

I personally use wrapper scripts c and p for copy and paste respectively, the first reading from standard input, the latter writing to standard output. That way, this works on all my development platforms:

(shell-command (format "echo '%s' | c" buffer-file-name))

I find this more reliable and configurable than using the Emacs clipboard support. For example, my c command copies the input to all 3 clipboards on Linux (primary, secondary, clipboard), so I can paste with either Ctrl-V or middle click.


This should work but it doesn't for me. (Ubuntu 14.04.1.) Namely, date | xclip and xclip file both work as advertised (storing the date or the contents of file to primary) if typed in the shell. But if I type either of these commands after M-! in emacs (and hit return) nothing happens; the cursor remains in the minibuffer as if expecting more input; and if I interrupt to regain control, nothing hsas been stored in primary.
OK, your idea works fine with xsel instead of xclip: (shell-command (format "echo '%s' | xsel -i" buffer-file-name)) -- and when made into an interactive command (as suggested in the most upvoted answer by @JeromeRadix above), this is a BIG WIN! Thanks!
D
DJJ

The simplest way and would be

(buffer-name)<(C-x)(C-e)> for the file name to appear in the echo area

(buffer-name)<(C-u)(C-x)(C-e)> would print the location <here>

Borrowing from Trey Jackson I came up with this:

(defun buffer-kill-path ()
  "copy buffer's full path to kill ring"
  (interactive)
  (kill-new (buffer-file-name)))

You can find more information on site


d
dolzenko

copy-buffer-file-name-as-kill from [0] does exactly what you need I think. It also has the option to copy just directory name, or just file name.

[0] http://www.emacswiki.org/emacs/download/buffer-extension.el