;;; -*- Mode:LISP; Package:USER; Base:10; Readtable:CL -*- (DEFUN PROCESS-DIRECTORY (DIR &OPTIONAL &REST OPTIONS &KEY SELECTIVE (RECURSIVE T) FILTER ONLY-LATEST (SINCE 0) (FUNCTION #'IDENTITY) &ALLOW-OTHER-KEYS &AUX WHOLE-DIR-LIST FILE) "A utility for processing directories. Options: :SELECTIVE One of NIL (default) or T. If not NIL, asks whether to copy each element. :RECURSIVE One of NIL, T (default), or :WILD meaning to use wild name, type, and version. :FILTER One of NIL (default) or a function to be called with the directory element as its single argument. If value returned by function is non-NIL, the element is copied. :ONLY-LATEST One of NIL (default) or T. If not NIL, force :NEWEST from the source directory. :SINCE date Copy only files created after date, a string or Universal Time (an integer). :FUNCTION The function to be called for each file. The argument list should look like: (file &rest options &key directory-list latest &allow-other-keys)" (SETQ DIR (FS:PARSE-PATHNAME DIR)) (SETQ DIR (SEND DIR :NEW-PATHNAME :NAME (IF (MEMQ (SEND DIR :NAME) '(NIL :UNSPECIFIC)) :WILD (SEND DIR :NAME)) :TYPE (IF (MEMQ (SEND DIR :TYPE) '(NIL :UNSPECIFIC)) :WILD (SEND DIR :TYPE)) :VERSION (IF ONLY-LATEST :NEWEST (IF (MEMQ (SEND DIR :VERSION) '(NIL :UNSPECIFIC)) :WILD (SEND DIR :VERSION))))) (UNLESS (NUMBERP SINCE) (SETQ SINCE (TIME:PARSE-UNIVERSAL-TIME SINCE))) (SETQ WHOLE-DIR-LIST (FS:DIRECTORY-LIST DIR)) (DOLIST (F WHOLE-DIR-LIST) (AND (SETQ FILE (CAR F)) (NOT (GET F :LINK-TO)) (OR (NOT SELECTIVE) (Y-OR-N-P "Process ~A ?" FILE)) (IF (get f :directory) (WHEN recursive (let* ((d (send file :directory)) (SUBDIRECTORY (cond ((CLI:LISTP D) (APPEND D (NCONS (SEND file :NAME)))) ((eq d ':root) (send file :name)) (t (LIST D (send file :NAME)))))) (APPLY 'process-directory (IF (EQ RECURSIVE :WILD) (SEND file :new-pathname :directory SUBDIRECTORY :name :wild :type :wild :version (SEND DIR :VERSION)) (SEND DIR :NEW-DIRECTORY SUBDIRECTORY)) options))) (WHEN (AND (> (GET F :CREATION-DATE) SINCE) (OR (NULL FILTER) (FUNCALL FILTER F))) (APPLY FUNCTION FILE :DIRECTORY-LIST (CDR F) :latest (or only-latest (determine-if-latest file whole-dir-list)) OPTIONS)))))) (defun determine-if-latest (f whole-dir-list) (let ((name (send f :name)) (type (send f :type)) (version (send f :version)) (directory (send f :directory))) (dolist (elt whole-dir-list t) (let ((x (car elt))) (and x (neq x f) (equal directory (send x :directory)) (equal name (send x :name)) (equal type (send x :type)) (> (send x :version) version) (return nil)))))) (defun sample-function (file &rest options &key directory-list latest &allow-other-keys) (format t "~&~S~@[ not~] latest" file (not latest)))