]> git.eshelyaron.com Git - emacs.git/commitdiff
Allow directory-files-recursively to follow symlinks
authorLars Ingebrigtsen <larsi@gnus.org>
Fri, 26 Jul 2019 15:03:42 +0000 (17:03 +0200)
committerLars Ingebrigtsen <larsi@gnus.org>
Sat, 27 Jul 2019 10:16:51 +0000 (12:16 +0200)
* doc/lispref/files.texi (Contents of Directories): Document it.

* lisp/files.el (directory-files-recursively): Allow following
symlinks.

doc/lispref/files.texi
etc/NEWS
lisp/files.el

index 0ea8a4f0a19acdcd1d3b8cb44eda40f8c3a59d3f..6be5a52837247b8ef72047b087059b7da974ba80 100644 (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
index 348b2124e66af529156ed85b170b5d7660556382..021e84c9a43bb6a42fe71edb433b91f1e141c186 100644 (file)
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -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.
 
 \f
 * Changes in Emacs 27.1 on Non-Free Operating Systems
index 81ca948bd2d3ff82dd87689fd24eb2605ec68287..184421f54f2d84ac2c3895541e28d40c19718875 100644 (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))