are processed in. If the order of processing is visible to the user,
then the user will probably be happier if you do sort the names.
+If @var{count} is non-@code{nil}, the function will return names of
+first @var{count} number of files, or names of all files, whichever
+occurs first. @var{count} has to be an integer greater than zero.
+
@example
@group
(directory-files "~lewis")
that can be read.
@end defun
+@defun directory-empty-p filename
+This utility function returns t if given @var{filename} is an
+accessible directory and it does not contain any files, i.e. is an
+empty directory. It will ignore '.' and '..' on systems that returns
+them as files in a directory.
+
+As a special case, this function will also return t if
+FILENAME is the empty string (""). This quirk is due to Emacs
+interpreting the empty string (in some cases) as the current
+directory.
+
+Symbolic links to directories count as directories.
+See @var{file-symlink-p} to distinguish symlinks.
+
+@end defun
+
@cindex recursive traverse of directory tree
@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 returns the list of file names of all the backup files
of its file argument.
++++
+** New utility function 'directory-empty-p'.
+This predicate tests whether a given filename is an accessible
+directory and whether it contains no other directories or files.
+
++++
+** 'directory-files' now takes an additional COUNT parameter.
+The parameter makes 'directory-files' return COUNT first file names
+from a directory. If MATCH is also given, the function will return
+first COUNT file names that match the expression.
+
+++
** The 'count-lines' function now takes an optional parameter to
ignore invisible lines.
;; Tree Dired
;;; utility functions
+(defun directory-empty-p (filename)
+ "Return t if FILENAME names an existing directory containing no
+other files. Return nil if FILENAME does not name a directory, or if
+there was trouble determining whether DIRECTORYNAME is a directory or empty.
+
+As a special case, this function will also return t if FILENAME is the
+empty string (\"\"). This quirk is due to Emacs interpreting the
+empty string (in some cases) as the current directory.
+
+Symbolic links to directories count as directories.
+See `file-symlink-p' to distinguish symlinks. "
+ (and (file-directory-p filename)
+ (null (directory-files
+ filename nil directory-files-no-dot-files-regexp t 1))))
(defun dired-in-this-tree-p (file dir)
;;"Is FILE part of the directory tree starting at DIR?"
(and (file-directory-p name)
(file-readable-p name)))
-(defun ange-ftp-directory-files (directory &optional full match
- &rest v19-args)
+(defun ange-ftp-directory-files (directory &optional full match nosort count)
(setq directory (expand-file-name directory))
(if (ange-ftp-ftp-name directory)
(progn
(if (or (not match) (string-match-p match f))
(setq files
(cons (if full (concat directory f) f) files))))
- (nreverse files)))
- (apply 'ange-ftp-real-directory-files directory full match v19-args)))
+ (nreverse files))
+ (when (natnump count)
+ (setq files (last files count))))
+ (apply 'ange-ftp-real-directory-files directory full match nosort count)))
(defun ange-ftp-directory-files-and-attributes
- (directory &optional full match nosort id-format)
+ (directory &optional full match nosort id-format count)
(setq directory (expand-file-name directory))
(if (ange-ftp-ftp-name directory)
(mapcar
(lambda (file)
(cons file (file-attributes (expand-file-name file directory))))
- (ange-ftp-directory-files directory full match nosort))
+ (ange-ftp-directory-files directory full match nosort count))
(ange-ftp-real-directory-files-and-attributes
- directory full match nosort id-format)))
+ directory full match nosort id-format count)))
(defun ange-ftp-file-attributes (file &optional id-format)
(setq file (expand-file-name file))
file-properties)))
(defun tramp-adb-handle-directory-files-and-attributes
- (directory &optional full match nosort id-format)
+ (directory &optional full match nosort id-format count)
"Like `directory-files-and-attributes' for Tramp files."
(unless (file-exists-p directory)
(tramp-error
(with-parsed-tramp-file-name (expand-file-name directory) nil
(copy-tree
(with-tramp-file-property
- v localname (format "directory-files-and-attributes-%s-%s-%s-%s"
- full match id-format nosort)
+ v localname (format "directory-files-and-attributes-%s-%s-%s-%s-%s"
+ full match id-format nosort count)
(with-current-buffer (tramp-get-buffer v)
(when (tramp-adb-send-command-and-check
v (format "%s -a -l %s"
(unless nosort
(setq result
(sort result (lambda (x y) (string< (car x) (car y))))))
- (delq nil
- (mapcar (lambda (x)
- (if (or (not match) (string-match-p match (car x)))
- x))
- result)))))))))
+
+ (setq result (delq nil
+ (mapcar (lambda (x) (if (or (not match)
+ (string-match-p
+ match (car x)))
+ x)) result)))
+ (when (natnump count)
+ (setq result (last result count))
+ (nreverse result))
+
+ result)))))))
(defun tramp-adb-get-ls-command (vec)
"Determine `ls' command and its arguments."
(tramp-rclone-flush-directory-cache v)))
(defun tramp-rclone-handle-directory-files
- (directory &optional full match nosort)
+ (directory &optional full match nosort count)
"Like `directory-files' for Tramp files."
(unless (file-exists-p directory)
(tramp-error
(with-parsed-tramp-file-name directory nil
(let ((result
(directory-files
- (tramp-rclone-local-file-name directory) full match)))
+ (tramp-rclone-local-file-name directory) full match count)))
;; Massage the result.
(when full
(let ((local (concat "^" (regexp-quote (tramp-rclone-mount-point v))))
(tramp-get-remote-gid v 'integer)))))))))
;; Directory listings.
-
(defun tramp-sh-handle-directory-files-and-attributes
- (directory &optional full match nosort id-format)
+ (directory &optional full match nosort id-format count)
"Like `directory-files-and-attributes' for Tramp files."
(unless id-format (setq id-format 'integer))
(unless (file-exists-p directory)
(sort result (lambda (x y) (string< (car x) (car y)))))
;; The scripts could fail, for example with huge file size.
(tramp-handle-directory-files-and-attributes
- directory full match nosort id-format)))))
+ directory full match nosort id-format count)))))
+;; FIXME Fix function to work with count parameter.
(defun tramp-do-directory-files-and-attributes-with-perl
(vec localname &optional id-format)
"Implement `directory-files-and-attributes' for Tramp files using a Perl script."
(when (stringp object) (tramp-error vec 'file-error object))
object))
+;; FIXME Fix function to work with count parameter.
(defun tramp-do-directory-files-and-attributes-with-stat
(vec localname &optional id-format)
"Implement `directory-files-and-attributes' for Tramp files using stat(1) command."
(tramp-error v 'file-error "%s `%s'" (match-string 0) filename)))))))
(defun tramp-smb-handle-directory-files
- (directory &optional full match nosort)
+ (directory &optional full match nosort count)
"Like `directory-files' for Tramp files."
(unless (file-exists-p directory)
(tramp-error
(delete nil
(mapcar (lambda (x) (when (string-match-p match x) x))
result))))
+
+ ;; return count number of results
+ (when (and (natnump count) (> count 0))
+ (setq result (nbutlast result (- (length result) count))))
+
;; Prepend directory.
(when full
(setq result
(setq directory (substring directory 0 -1)))
directory)
-(defun tramp-handle-directory-files (directory &optional full match nosort)
+(defun tramp-handle-directory-files (directory &optional full match nosort count)
"Like `directory-files' for Tramp files."
(unless (file-exists-p directory)
(tramp-error
(when (or (null match) (string-match-p match item))
(push (if full (concat directory item) item)
result)))
- (if nosort result (sort result #'string<)))))
+ (unless nosort
+ (setq result (sort result #'string<)))
+ (when (natnump count)
+ (setq result (last file count))
+ (nreverse files)))))
(defun tramp-handle-directory-files-and-attributes
- (directory &optional full match nosort id-format)
+ (directory &optional full match nosort id-format count)
"Like `directory-files-and-attributes' for Tramp files."
(mapcar
(lambda (x)
(cons x (file-attributes
(if full x (expand-file-name x directory)) id-format)))
- (directory-files directory full match nosort)))
+ (directory-files directory full match nosort count)))
(defun tramp-handle-dired-uncache (dir)
"Like `dired-uncache' for Tramp files."
Lisp_Object
directory_files_internal (Lisp_Object directory, Lisp_Object full,
Lisp_Object match, Lisp_Object nosort, bool attrs,
- Lisp_Object id_format)
+ Lisp_Object id_format, Lisp_Object return_count)
{
+ ptrdiff_t ind = 0, last = MOST_POSITIVE_FIXNUM;
+
+ if (!NILP(return_count))
+ {
+ CHECK_FIXNAT(return_count);
+ last = XFIXNAT (return_count);
+ }
+
if (!NILP (match))
CHECK_STRING (match);
else
finalname = name;
+ if (ind == last)
+ break;
+ ind ++;
+
list = Fcons (attrs ? Fcons (finalname, fileattrs) : finalname, list);
}
}
-DEFUN ("directory-files", Fdirectory_files, Sdirectory_files, 1, 4, 0,
+DEFUN ("directory-files", Fdirectory_files, Sdirectory_files, 1, 5, 0,
doc: /* Return a list of names of files in DIRECTORY.
There are three optional arguments:
If FULL is non-nil, return absolute file names. Otherwise return names
matches the regexp MATCH.
If NOSORT is non-nil, the list is not sorted--its order is unpredictable.
Otherwise, the list returned is sorted with `string-lessp'.
- NOSORT is useful if you plan to sort the result yourself. */)
+ NOSORT is useful if you plan to sort the result yourself.
+If COUNT is non-nil and a natural number, the function will return
+ COUNT number of file names (if so many are present). */)
(Lisp_Object directory, Lisp_Object full, Lisp_Object match,
- Lisp_Object nosort)
+ Lisp_Object nosort, Lisp_Object count)
{
directory = Fexpand_file_name (directory, Qnil);
call the corresponding file name handler. */
Lisp_Object handler = Ffind_file_name_handler (directory, Qdirectory_files);
if (!NILP (handler))
- return call5 (handler, Qdirectory_files, directory,
- full, match, nosort);
+ return call6 (handler, Qdirectory_files, directory,
+ full, match, nosort, count);
- return directory_files_internal (directory, full, match, nosort, false, Qnil);
+ return directory_files_internal (directory, full, match, nosort,
+ false, Qnil, count);
}
DEFUN ("directory-files-and-attributes", Fdirectory_files_and_attributes,
- Sdirectory_files_and_attributes, 1, 5, 0,
+ Sdirectory_files_and_attributes, 1, 6, 0,
doc: /* Return a list of names of files and their attributes in DIRECTORY.
Value is a list of the form:
ID-FORMAT specifies the preferred format of attributes uid and gid, see
`file-attributes' for further documentation.
On MS-Windows, performance depends on `w32-get-true-file-attributes',
-which see. */)
+which see.
+If COUNT is non-nil and a natural number, the function will return
+ COUNT number of file names (if so many are present). */)
(Lisp_Object directory, Lisp_Object full, Lisp_Object match,
- Lisp_Object nosort, Lisp_Object id_format)
+ Lisp_Object nosort, Lisp_Object id_format, Lisp_Object count)
{
directory = Fexpand_file_name (directory, Qnil);
Lisp_Object handler
= Ffind_file_name_handler (directory, Qdirectory_files_and_attributes);
if (!NILP (handler))
- return call6 (handler, Qdirectory_files_and_attributes,
- directory, full, match, nosort, id_format);
+ return call7 (handler, Qdirectory_files_and_attributes,
+ directory, full, match, nosort, id_format, count);
return directory_files_internal (directory, full, match, nosort,
- true, id_format);
+ true, id_format, count);
}
\f
extern void syms_of_dired (void);
extern Lisp_Object directory_files_internal (Lisp_Object, Lisp_Object,
Lisp_Object, Lisp_Object,
- bool, Lisp_Object);
+ bool, Lisp_Object, Lisp_Object);
/* Defined in term.c. */
extern int *char_ins_del_vector;
process. */
procdir = build_string ("/proc");
match = build_string ("[0-9]+");
- proclist = directory_files_internal (procdir, Qnil, match, Qt, false, Qnil);
+ proclist = directory_files_internal (procdir, Qnil, match, Qt,
+ false, Qnil, Qnil);
/* `proclist' gives process IDs as strings. Destructively convert
each string into a number. */
--- /dev/null
+;;; dired-tests.el --- Tests for directory-files in dired.c -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2020 Free Software Foundation, Inc.
+
+;; Author: Arthur Miller <arthur.miller@live.com>
+;; Keywords:
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; These tests check mostly for correct behaviour with COUNT argument.
+
+;;; Code:
+(require 'ert)
+
+(ert-deftest directory-files-tests ()
+ (let ((testdir (expand-file-name "directory-files-test"
+ (temporary-file-directory)))
+ (nod directory-files-no-dot-files-regexp))
+ (unwind-protect
+ (progn
+ (when (file-directory-p testdir)
+ (delete-directory testdir t))
+
+ (make-directory testdir)
+ (when (file-directory-p testdir)
+ ;; directory-empty-p: test non-existent dir
+ (should-not (directory-empty-p "some-imaginary-dir"))
+ (should (= 2 (length (directory-files testdir))))
+ ;; directory-empty-p: test empty dir
+ (should (directory-empty-p testdir))
+ (should-not (directory-files testdir nil nod t 1))
+ (dolist (file '(a b c d))
+ (make-empty-file (expand-file-name (symbol-name file) testdir)))
+ (should (= 6 (length (directory-files testdir))))
+ (should (equal "abcd" (mapconcat 'identity (directory-files
+ testdir nil nod) "")))
+ (should (= 2 (length (directory-files testdir nil "[bc]"))))
+ (should (= 3 (length (directory-files testdir nil nod nil 3))))
+ (dolist (file '(5 4 3 2 1))
+ (make-empty-file (expand-file-name (number-to-string
+ file) testdir)))
+ ;;(should (= 0 (length (directory-files testdir nil "[0-9]" t -1))))
+ (should (= 5 (length (directory-files testdir nil "[0-9]" t))))
+ (should (= 5 (length (directory-files testdir nil "[0-9]" t 50))))
+ (should-not (directory-empty-p testdir)))
+
+ (delete-directory testdir t)))))
+
+(ert-deftest directory-files-and-attributes-tests ()
+ (let ((testdir (expand-file-name "directory-files-test"
+ (temporary-file-directory)))
+ (nod directory-files-no-dot-files-regexp))
+
+ (unwind-protect
+ (progn
+ (when (file-directory-p testdir)
+ (delete-directory testdir t))
+
+ (make-directory testdir)
+ (when (file-directory-p testdir)
+ (should (= 2 (length (directory-files testdir))))
+ (should-not (directory-files-and-attributes testdir t nod t 1))
+ (dolist (file '(a b c d))
+ (make-directory (expand-file-name (symbol-name file) testdir)))
+ (should (= 6 (length (directory-files-and-attributes testdir))))
+ (dolist (dir (directory-files-and-attributes testdir t nod))
+ (should (file-directory-p (car dir)))
+ (should-not (file-regular-p (car dir))))
+ (should (= 2 (length
+ (directory-files-and-attributes testdir nil
+ "[bc]"))))
+ (should (= 3 (length
+ (directory-files-and-attributes testdir nil nod
+ nil nil 3))))
+ (dolist (file '(5 4 3 2 1))
+ (make-empty-file (expand-file-name (number-to-string file)
+ testdir)))
+ ;; (should (= 0 (length (directory-files-and-attributes testdir nil
+ ;; "[0-9]" t
+ ;; nil -1))))
+ (should (= 5 (length
+ (directory-files-and-attributes testdir nil
+ "[0-9]" t))))
+ (should (= 5 (length
+ (directory-files-and-attributes testdir nil
+ "[0-9]" t
+ nil 50))))))
+ (when (file-directory-p testdir)
+ (delete-directory testdir t)))))
+
+(provide 'dired-tests)
+;;; dired-tests.el ends here