Emacs Lisp: Walk Directory, List Files

By Xah Lee. Date: . Last updated: .

Here's how to walk directory.

List Directory (No Subdir)

directory-files
(directory-files DIRECTORY &optional FULL MATCH NOSORT COUNT)

Return a list of paths of file or dir in DIRECTORY. (No Subdir)

parameters:

  • FULL → if true, return full path.
  • MATCH → is a Regular Expression. Only return matched file names.
  • NOSORT → if true, result is not sorted.
  • COUNT → return max of n items.

🛑 WARNING: the returned path may include the unix dot "." (means current dir) and dot dot ".." (means parent dir). To exclude them, use a MATCH regex that does not match dot or dotdot e.g. \\.jpg$ or use directory-files-no-dot-files-regexp

;; list dir content, top level only

;; result include dir
;; result also include . and ..

(directory-files "~/Downloads/" nil "." t 5)

;; sample output
;; (
;; "books"
;; "Advantage360.pdf"
;; "821716.nb"
;; ".."
;; "."
;; )

;; HHHH---------------------------------------------------

;; use directory-files-no-dot-files-regexp
;; to exclude . and ..
(directory-files "~/Downloads/" nil directory-files-no-dot-files-regexp t 5)

;; sample output
;; (
;; "cll.txt"
;; "books_GyF84.jpg"
;; "biden-laptop-emls.zip"
;; "Advantage360-SmartSet-QSG-v7-25-22.pdf"
;; "821716.nb"
;; )

;; HHHH---------------------------------------------------

;; show jpg files
(directory-files "~/Downloads/" nil "\\.jpg$" t 5)

;; sample output
;; ("books_GyF84.jpg")

List Directory and All Subdir

directory-files-recursively
(directory-files-recursively DIR REGEXP &optional INCLUDE-DIRECTORIES PREDICATE FOLLOW-SYMLINKS)

Return list of all files under directory DIR whose names match REGEXP.

REGEXP is matched against file name only, not full path.

  • Returned paths are full paths.
  • Unix dot and dotdot dirs are not included.
  • All nested subdirectories are included, and their content.
  • Items are returned in depth first order.
  • Items from each directory are sorted in alphabetical order.
  • INCLUDE-DIRECTORIES true means also show directories in result.
  • dir path in result does not end in slash.
;; list dir and and all subdir

(directory-files-recursively
  "~/Downloads/"
  "\\.jpg$"
  )

;; sample output

;; (
;; "~/Downloads/xx2023-03-11/x1/j4S74.jpg"
;; "~/Downloads/xx2023-03-11/x1/q5kRh.jpg"
;; "~/Downloads/xx2023-03-11/x1/5RkPY.jpg"
;; "~/Downloads/xx2023-03-11/tnRKp.jpg"
;; )

Filter by Dir Depth Level

Skipping Subdir

In other programing languages (perl python golang), usually the dir walker lets you skip some specified directory. The walker calls a doFile function you write, and pass current dir or file, so you can skip it to prevent going into.

In elisp, there's a package find-lisp.el that lets you use a regex to filter dir, but is very slow. I do not recommend it. [Emacs Lisp: find-lisp.el]

To skip some subdir, it's faster if you just use directory-files-recursively then filter result.

(setq
 skipDirs
 [
  "ergoemacs_org/emacs_manual/"
  "xahlee_info/REC-SVG11-20110816/"
  "xahlee_info/clojure-doc-1.8/"
  ])

(seq-filter
 (lambda (path)
   (not (seq-some
         (lambda (x) (string-match x path))
         skipDirs )))
 (directory-files-recursively "/Users/xah/web/xahlee_info/" "\\.svg$" ))

to filter a list, see Emacs Lisp: Sequence Functions

Other Functions

Reference

Emacs Lisp File/Buffer