Code to insert a file name using Emacs’s file name completion.

  (defun my-insert-file-name (filename &optional args)
    "Insert name of file FILENAME into buffer after point.
  Prefixed with \\[universal-argument], expand the file name to
  its fully canocalized path.  See `expand-file-name'.
  Prefixed with \\[negative-argument], use relative path to file
  name from current directory, `default-directory'.  See
  The default with no prefix is to insert the file name exactly as
  it appears in the minibuffer prompt."
    ;; Based on insert-file in Emacs -- ashawley 20080926
    (interactive "*fInsert file name: \nP")
    (cond ((eq '- args)
           (insert (file-relative-name filename)))
          ((not (null args))
           (insert (expand-file-name filename)))
           (insert filename))))
  (global-set-key "\C-c\C-i" 'my-insert-file-name)


  C-c C-i ~/.emacs RET

will insert the file name as it appears in the MiniBuffer.

If you want the full path to the file, you can have it “expanded” with a PrefixArgument.


  C-u C-c C-i ~/.emacs RET

will insert


into the buffer.


  M-- C-c C-i ~/.emacs RET

will insert the relative path to the file, in this case just the file name.


Here’s a summary of the above,

Key sequenceInserted text
C-c C-i ~/.emacs RET~/.emacs
C-u C-c C-i ~/.emacs RET/home/user/.emacs
C-- C-c C-i ~/.emacs RET.emacs

Based on a blog post by RodrigoLazo.

Link (site) appears dead, so I can’t comment there: but isn’t “file-relative-name” without a directory argument equivalent to file-name-nondirectory? That one’s faster, even though it doesn’t really matter here.

To replace the file at point, you can use the following extension of FindFileAtPoint.

  (autoload 'ffap-guesser "ffap")
  (autoload 'ffap-read-file-or-url "ffap")
  (defun my-replace-file-at-point (currfile newfile)
    "Replace CURRFILE at point with NEWFILE.
  When interactive, CURRFILE will need to be confirmed by user
  and will need to exist on the file system to be recognized,
  unless it is a URL.
  NEWFILE does not need to exist.  However, Emacs's minibuffer
  completion can help if it needs to be.
  Based on `ffap'."
     (let ((currfile (ffap-read-file-or-url "Replace filename: "
       (list currfile
             (ffap-read-file-or-url (format "Replace `%s' with: "
                                            currfile) currfile))))
      (if (or (looking-at (regexp-quote currfile))
              (let ((filelen (length currfile))
                    (opoint (point))
                    (limit (+ (point) (length currfile))))
                  (goto-char (1- filelen))
                  (and (search-forward currfile limit
                       (< (match-beginning 0) opoint))
                       (>= (match-end 0) opoint))))
          (replace-match newfile)
        (error "No file at point to replace"))))
  (global-set-key "\C-c\C-v" 'my-replace-file-at-point)

Ivy mode

If you use ivy-mode, the following code can be used to insert the file name in the counsel-find-file minibuffer (which is usually bound to “C-x C-f” to replace find-files).

  (ivy-add-actions t
                   '(("I" (lambda (x) (with-ivy-window (insert x))) "insert")))
  (ivy-add-actions 'counsel-find-file
                   '(("F" (lambda (x) (with-ivy-window (insert (file-relative-name x))))
                      "insert relative file name")
                     ("B" (lambda (x)
                              (insert (file-name-nondirectory (replace-regexp-in-string "/\\'" "" x)))))
                      "insert file name without any directory information")))

Then after calling up the minibuffer, use “M-o F”, “M-o I” or “M-o B” to insert the file path in the minibuffer.

See also CompleteFileName, FindFileAtPoint.

CategoryEditing CategoryFiles