arvidj
arvidj

Reputation: 777

Emacs lisp: How can I get the newest file in a directory?

Given the path of a directory, how can I return the path of the newest file in that directory?

Upvotes: 7

Views: 1025

Answers (4)

Preminster
Preminster

Reputation: 495

via xuchunyang, except his version sorts in reverse lexicographic order instead of modification time. This one is slower but does get most recently modified file:

(defun latest-file (path &optional match)
    (car (sort (directory-files path 'full match t) #'file-newer-than-file-p)))

;; most recently modified file in ~/.emacs.d (non-recursive)
(latest-file "~/.emacs.d")
;; most recently modified file in ~/.emacs.d with .el extension
(latest-file "~/.emacs.d" ".*\\.el$")

Upvotes: 0

sparkly-spark
sparkly-spark

Reputation: 11

If you want to do it without dependencies

  • directory-files-and-attributes gives us a list of files and directories with attributes
    • the 4th arg NOSORT is a bool and does not take a function as the top answer suggests

    (directory-files-and-attributes DIRECTORY &optional FULL MATCH NOSORT ID-FORMAT)
    If NOSORT is non-nil, the list is not sorted--its order is unpredictable. NOSORT is useful if you plan to sort the result yourself.

    • attributes are in the format of file-attributes - which gives us the modification time and whether the item is a file or directory
    1. t for directory, string (name linked to) for symbolic link, or nil.\
    2. Last modification time, likewise. This is the time of the last
(car
 (seq-find
  '(lambda (x) (not (nth 1 x))) ; non-directory
  (sort
   (directory-files-and-attributes path 'full nil t)
   '(lambda (x y) (time-less-p (nth 5 y) (nth 5 x)))))) ; last modified first: y < x

Upvotes: 1

xuchunyang
xuchunyang

Reputation: 959

Using built-in APIs can achieve as well:

(defun latest-file (path)
  "Get latest file (including directory) in PATH."
  (car (directory-files path 'full nil #'file-newer-than-file-p)))

(latest-file "~/.emacs.d") ;; => "/Users/xcy/.emacs.d/var"

If you also needs files under sub-directory, use directory-files-recursively rather than directory-files. If you want to exclude directories, filter the file/directory list first by using file-directory-p.

Upvotes: 7

arvidj
arvidj

Reputation: 777

Using f:

(defun aj-fetch-latest (path)
  (let ((e (f-entries path)))
    (car (sort e (lambda (a b)
                   (not (time-less-p (aj-mtime a)
                                     (aj-mtime b))))))))
(defun aj-mtime (f) (let ((attrs (file-attributes f))) (nth 5 attrs)))

Upvotes: 3

Related Questions