diff options
| author | Lars Ingebrigtsen | 2019-07-26 17:03:42 +0200 |
|---|---|---|
| committer | Lars Ingebrigtsen | 2019-07-27 12:16:51 +0200 |
| commit | 0779b1c31d27c348f6f2a94c5aa1a64de855a39d (patch) | |
| tree | f4d3a1ef72a03c3afa56e3f076a3a4216c7538d6 | |
| parent | 2cc5bb67ffde05384dfb4b7c24ea3e4255205390 (diff) | |
| download | emacs-0779b1c31d27c348f6f2a94c5aa1a64de855a39d.tar.gz emacs-0779b1c31d27c348f6f2a94c5aa1a64de855a39d.zip | |
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.
| -rw-r--r-- | doc/lispref/files.texi | 5 | ||||
| -rw-r--r-- | etc/NEWS | 4 | ||||
| -rw-r--r-- | lisp/files.el | 23 |
3 files changed, 22 insertions, 10 deletions
diff --git a/doc/lispref/files.texi b/doc/lispref/files.texi index 0ea8a4f0a19..6be5a528372 100644 --- a/doc/lispref/files.texi +++ b/doc/lispref/files.texi | |||
| @@ -2919,7 +2919,7 @@ An error is signaled if @var{directory} is not the name of a directory | |||
| 2919 | that can be read. | 2919 | that can be read. |
| 2920 | @end defun | 2920 | @end defun |
| 2921 | 2921 | ||
| 2922 | @defun directory-files-recursively directory regexp &optional include-directories predicate | 2922 | @defun directory-files-recursively directory regexp &optional include-directories predicate follow-symlinks |
| 2923 | Return all files under @var{directory} whose names match @var{regexp}. | 2923 | Return all files under @var{directory} whose names match @var{regexp}. |
| 2924 | This function searches the specified @var{directory} and its | 2924 | This function searches the specified @var{directory} and its |
| 2925 | sub-directories, recursively, for files whose basenames (i.e., without | 2925 | 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 | |||
| 2940 | neither @code{nil} nor @code{t}, it should be a function that takes | 2940 | neither @code{nil} nor @code{t}, it should be a function that takes |
| 2941 | one parameter (the subdirectory name) and should return non-@code{nil} | 2941 | one parameter (the subdirectory name) and should return non-@code{nil} |
| 2942 | if the directory is to be descended into. | 2942 | if the directory is to be descended into. |
| 2943 | |||
| 2944 | Symbolic links to subdirectories are not followed by default, but if | ||
| 2945 | @var{follow-symlinks} is non-@code{nil}, they are followed. | ||
| 2943 | @end defun | 2946 | @end defun |
| 2944 | 2947 | ||
| 2945 | @defun directory-files-and-attributes directory &optional full-name match-regexp nosort id-format | 2948 | @defun directory-files-and-attributes directory &optional full-name match-regexp nosort id-format |
| @@ -2407,7 +2407,9 @@ the Emacs Lisp manual. | |||
| 2407 | 2407 | ||
| 2408 | +++ | 2408 | +++ |
| 2409 | ** `directory-files-recursively' can now take an optional PREDICATE | 2409 | ** `directory-files-recursively' can now take an optional PREDICATE |
| 2410 | parameter to control descending into subdirectories. | 2410 | parameter to control descending into subdirectories, and a |
| 2411 | FOLLOW-SYMLINK parameter to say that symbolic links that point to | ||
| 2412 | other directories should be followed. | ||
| 2411 | 2413 | ||
| 2412 | 2414 | ||
| 2413 | * Changes in Emacs 27.1 on Non-Free Operating Systems | 2415 | * Changes in Emacs 27.1 on Non-Free Operating Systems |
diff --git a/lisp/files.el b/lisp/files.el index 81ca948bd2d..184421f54f2 100644 --- a/lisp/files.el +++ b/lisp/files.el | |||
| @@ -813,7 +813,8 @@ The path separator is colon in GNU and GNU-like systems." | |||
| 813 | (error "No such directory found via CDPATH environment variable")))) | 813 | (error "No such directory found via CDPATH environment variable")))) |
| 814 | 814 | ||
| 815 | (defun directory-files-recursively (dir regexp | 815 | (defun directory-files-recursively (dir regexp |
| 816 | &optional include-directories predicate) | 816 | &optional include-directories predicate |
| 817 | follow-symlinks) | ||
| 817 | "Return list of all files under DIR that have file names matching REGEXP. | 818 | "Return list of all files under DIR that have file names matching REGEXP. |
| 818 | This function works recursively. Files are returned in \"depth | 819 | This function works recursively. Files are returned in \"depth |
| 819 | first\" order, and files from each directory are sorted in | 820 | first\" order, and files from each directory are sorted in |
| @@ -827,7 +828,10 @@ PREDICATE can be either nil (which means that all subdirectories | |||
| 827 | are descended into), t (which means that subdirectories that | 828 | are descended into), t (which means that subdirectories that |
| 828 | can't be read are ignored), or a function (which is called with | 829 | can't be read are ignored), or a function (which is called with |
| 829 | name name of the subdirectory and should return non-nil if the | 830 | name name of the subdirectory and should return non-nil if the |
| 830 | subdirectory is to be descended into)." | 831 | subdirectory is to be descended into). |
| 832 | |||
| 833 | If FOLLOW-SYMLINKS, symbolic links that point to directories are | ||
| 834 | followed. Note that this can lead to infinite recursion." | ||
| 831 | (let* ((result nil) | 835 | (let* ((result nil) |
| 832 | (files nil) | 836 | (files nil) |
| 833 | (dir (directory-file-name dir)) | 837 | (dir (directory-file-name dir)) |
| @@ -841,19 +845,22 @@ subdirectory is to be descended into)." | |||
| 841 | (let* ((leaf (substring file 0 (1- (length file)))) | 845 | (let* ((leaf (substring file 0 (1- (length file)))) |
| 842 | (full-file (concat dir "/" leaf))) | 846 | (full-file (concat dir "/" leaf))) |
| 843 | ;; Don't follow symlinks to other directories. | 847 | ;; Don't follow symlinks to other directories. |
| 844 | (when (and (not (file-symlink-p full-file)) | 848 | (when (and (or (not (file-symlink-p full-file)) |
| 849 | (and (file-symlink-p full-file) | ||
| 850 | follow-symlinks)) | ||
| 845 | ;; Allow filtering subdirectories. | 851 | ;; Allow filtering subdirectories. |
| 846 | (or (eq predicate nil) | 852 | (or (eq predicate nil) |
| 847 | (eq predicate t) | 853 | (eq predicate t) |
| 848 | (funcall predicate full-file))) | 854 | (funcall predicate full-file))) |
| 849 | (let ((sub-files | 855 | (let ((sub-files |
| 850 | (if (eq predicate t) | 856 | (if (eq predicate t) |
| 851 | (condition-case _ | 857 | (ignore-error file-error |
| 852 | (directory-files-recursively | 858 | (directory-files-recursively |
| 853 | full-file regexp include-directories) | 859 | full-file regexp include-directories |
| 854 | (file-error nil)) | 860 | predicate follow-symlinks)) |
| 855 | (directory-files-recursively | 861 | (directory-files-recursively |
| 856 | full-file regexp include-directories)))) | 862 | full-file regexp include-directories |
| 863 | predicate follow-symlinks)))) | ||
| 857 | (setq result (nconc result sub-files)))) | 864 | (setq result (nconc result sub-files)))) |
| 858 | (when (and include-directories | 865 | (when (and include-directories |
| 859 | (string-match regexp leaf)) | 866 | (string-match regexp leaf)) |