Get the current file’s path in Emacs Lisp

To get the current file’s path in Emacs Lisp, use load-file-name. This only works when a file is loaded, so running it directly in Emacs will produce an empty value, as no file is being loaded when the variable is accessed:

(message (format "load-file-name: %s" load-file-name))
load-file-name: nil

However, with the expression above saved to a file named load-file-name.el, the file name is printed to the messages buffer when it’s loaded through load-file:

(load-file "load-file-name.el")
load-file-name: /Users/jeff/notes/load-file-name.el

It also works in batch mode, when the file is loaded with the --load flag:

emacs --batch --load load-file-name.el
load-file-name: /Users/jeff/notes/load-file-name.el

Remembering the file name for later

Trying to access the load-file-name variable later once again results in an empty value. By the time the function is called, the file is done loading, and the load-file-name variable is emptied. This means putting it in a function and calling that from outside of the file won’t work:

(defun jk/load-file-name ()
  (format "load-file-name: %s" load-file-name))

Loading the file and then evaluating the function produces a empty value:

emacs --batch --load load-file-name-fun.el --eval "(message (jk/load-file-name))"
load-file-name: nil

Instead, bind the value to a variable name when the file loads, then use the variable instead of calling load-file-name directly:

(setq jk/load-file-name load-file-name)

(defun jk/load-file-name ()
  (format "load-file-name: %s" jk/load-file-name))

With the variable in place, loading the file and then evaluating the function returns the file’s name, as the function is simply returning the variable’s previously set value:

emacs --batch --load load-file-name-set.el --eval "(message (jk/load-file-name))"
load-file-name: /Users/jeff/notes/load-file-name-set.el