Emacs Lisp: Walk Directory, List Files
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
directory-empty-p