Elisp: Walk Directory
Here's how to walk 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
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
then filter result.
(setq skipDirs [ "ergoemacs_org/emacs_manual/" "xahlee_info/REC-SVG11-20110816/" "xahlee_info/clojure-doc-1.8/" "xahlee_info/js_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-some are in emacs 25.
[see Elisp: Sequence Functions]