Elisp: Walk Directory

By Xah Lee. Date: . Last updated: .

Here's how to walk directory.

List Directory

(directory-files DIRECTORY &optional FULL MATCH NOSORT) → Return a list of names of files in DIRECTORY. If FULL is non-nil, return absolute file names. If MATCH is non-nil, only return matched files. If NOSORT is non-nil, the list is not sorted, order is unpredictable.

;; walk dir

(mapc
 (lambda (x) (insert x "\n"))
 (directory-files "/Users/x/em/emacs/i" nil "\.jpg$" t))

;; sample output

;; ztn_emacs_pinky_wedge_2018-02-24.jpg
;; xah_lee_photo_2018-06-28.jpg
;; xah-fly-keys_kinesis_2017-09_60363.jpg
;; todo_list_crossout_nothing.jpg
;; the_book_of_shen_lang.jpg
;; sun_type_6_keyboard_meta_compose_altgraph_keys.jpg

[see Elisp: Regex Tutorial]

Note: in unix, directory is considered a special file. So, in emacs doc and other unix doc, the term “file name” may also refer to directory name.

List Directory and All Subdir

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

Return list of all files under DIR and all its subdir that have file names matching REGEXP. (note, the match is done against file name only, not full path.) Returned list elements are full path. Optional argument INCLUDE-DIRECTORIES non-nil means also include in the output directories whose names match REGEXP.

;; walk dir and all subdir

(mapc (lambda (x) (insert x "\n"))
      (directory-files-recursively "/Users/x/em/" "\.jpg$" ))

;; sample output

;; /Users/x/em/emacs/i/Apple_G4_iBook_Snow_Euro_layout_keyboard_62224.jpg
;; /Users/x/em/emacs/i/Apple_iBook_G4_Snow_77735.jpg
;; /Users/x/em/misc/i/typing_of_the_dead_36588.jpg
;; /Users/x/em/misc/i/vim_fitness.jpg
;; /Users/x/em/tn/emacs/emacs_logo/emacs_logo_large.jpg
;; /Users/x/em/tn/emacs/i/unicode/Carbon_emacs_22_unicode.jpg

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. [Elisp: 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/"
  "xahlee_info/javascript_es2016/"
  "xahlee_info/python_doc_3.3.3/"
  ])

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

seq-filter and seq-some are in emacs 25.

[see Elisp: Sequence Functions]

Elisp, Writing Scritpts

  1. Run Elisp Script in Shell
  2. Get Command Line Args
  3. Read File
  4. Read File Content as List
  5. Write File
  6. Print, Output
  7. Format String
  8. Walk Dir
  9. Call Shell Command
  10. Get Script Name at Run Time
Patreon me $5 patreon

Or Buy Xah Emacs Tutorial

Or buy a nice keyboard: Best Keyboard for Emacs

If you have a question, put $5 at patreon and message me.