I have a set of directories. For each directory I have a set of relative file names. I would like to select any of these relative filenames using completion, and then later reconstruct the absolute path of the filename.
In order to create a list of relative filenames for a given directory, I created this function:
(defun my-get-dir-files (dir pat &optional rel-dir)
"Finds relative filenames. Returns a list of relative filenames/pathnames to
directory `dir' matching pattern `pat'. The variable `rel-dir` is only used internally
by recursive calls and should usually not be supplied.
IMPORTANT: This function uses recursion. To avoid excessive copying of lists,
the variable `files' is used as a dynamic list variable, and is assumed to be
defined as non-lexical dynamic variable in the caller using a let binding"
(let ((dir-files nil)
(cur-dir nil))
(unless rel-dir (setq rel-dir ""))
(setq cur-dir (expand-file-name rel-dir dir))
(setq dir-files (directory-files cur-dir nil nil t))
(dolist (name dir-files)
(unless (or (string= name ".") (string= name ".."))
(let ((fn (expand-file-name name cur-dir)))
(if (file-directory-p fn)
(let ((new-rel-dir nil))
(if (string= "" rel-dir)
(setq new-rel-dir name)
(setq new-rel-dir (concat rel-dir "/" name)))
(my-get-dir-files dir pat new-rel-dir)) ;; recursive call
(when (string-match pat name)
(let ((rel-fn nil))
(if (string= "" rel-dir)
(setq rel-fn name)
(setq rel-fn (concat rel-dir "/" name))
(setq files (append files `(,rel-fn))))))))))))
Then I plan to use code like:
(let ((dir "/home/hakon/dir1")
(files nil))
(my-get-dir-files dir "\\.el$")
files)
to set the list variable files
.
One thing that worries me here is the use of the (non-lexical) dynamic variable files
. Can or should this be avoided?
According to the manual I have violated this principle:
If a variable has no global definition, use it as a local variable only within a binding construct