Allow directory-files-recursively to follow symlinks

* doc/lispref/files.texi (Contents of Directories): Document it.

* lisp/files.el (directory-files-recursively): Allow following
symlinks.
This commit is contained in:
Lars Ingebrigtsen 2019-07-26 17:03:42 +02:00
parent 2cc5bb67ff
commit 0779b1c31d
3 changed files with 22 additions and 10 deletions

View file

@ -2919,7 +2919,7 @@ An error is signaled if @var{directory} is not the name of a directory
that can be read.
@end defun
@defun directory-files-recursively directory regexp &optional include-directories predicate
@defun directory-files-recursively directory regexp &optional include-directories predicate follow-symlinks
Return all files under @var{directory} whose names match @var{regexp}.
This function searches the specified @var{directory} and its
sub-directories, recursively, for files whose basenames (i.e., without
@ -2940,6 +2940,9 @@ instance, if it's not readable by this user) are ignored. If it's
neither @code{nil} nor @code{t}, it should be a function that takes
one parameter (the subdirectory name) and should return non-@code{nil}
if the directory is to be descended into.
Symbolic links to subdirectories are not followed by default, but if
@var{follow-symlinks} is non-@code{nil}, they are followed.
@end defun
@defun directory-files-and-attributes directory &optional full-name match-regexp nosort id-format

View file

@ -2407,7 +2407,9 @@ the Emacs Lisp manual.
+++
** `directory-files-recursively' can now take an optional PREDICATE
parameter to control descending into subdirectories.
parameter to control descending into subdirectories, and a
FOLLOW-SYMLINK parameter to say that symbolic links that point to
other directories should be followed.
* Changes in Emacs 27.1 on Non-Free Operating Systems

View file

@ -813,7 +813,8 @@ The path separator is colon in GNU and GNU-like systems."
(error "No such directory found via CDPATH environment variable"))))
(defun directory-files-recursively (dir regexp
&optional include-directories predicate)
&optional include-directories predicate
follow-symlinks)
"Return list of all files under DIR that have file names matching REGEXP.
This function works recursively. Files are returned in \"depth
first\" order, and files from each directory are sorted in
@ -827,7 +828,10 @@ PREDICATE can be either nil (which means that all subdirectories
are descended into), t (which means that subdirectories that
can't be read are ignored), or a function (which is called with
name name of the subdirectory and should return non-nil if the
subdirectory is to be descended into)."
subdirectory is to be descended into).
If FOLLOW-SYMLINKS, symbolic links that point to directories are
followed. Note that this can lead to infinite recursion."
(let* ((result nil)
(files nil)
(dir (directory-file-name dir))
@ -841,19 +845,22 @@ subdirectory is to be descended into)."
(let* ((leaf (substring file 0 (1- (length file))))
(full-file (concat dir "/" leaf)))
;; Don't follow symlinks to other directories.
(when (and (not (file-symlink-p full-file))
(when (and (or (not (file-symlink-p full-file))
(and (file-symlink-p full-file)
follow-symlinks))
;; Allow filtering subdirectories.
(or (eq predicate nil)
(eq predicate t)
(funcall predicate full-file)))
(let ((sub-files
(if (eq predicate t)
(condition-case _
(directory-files-recursively
full-file regexp include-directories)
(file-error nil))
(ignore-error file-error
(directory-files-recursively
full-file regexp include-directories
predicate follow-symlinks))
(directory-files-recursively
full-file regexp include-directories))))
full-file regexp include-directories
predicate follow-symlinks))))
(setq result (nconc result sub-files))))
(when (and include-directories
(string-match regexp leaf))