#| > (comprehend-directory #p"recordings/*.*") (((NAMESTRING . "9021-1680324909_855162500-call_4036.m4a") (DECODED-TIME (YEA . 2023) (MON . 3) (DAY . 31) (HOU . 23) (MIN . 55) (SEC . 9)) (TGID . 9021) (UNIX-TIME . 1680324909) (LOCATION? . 855162500) (UNUSED . CALL) (INDEX . 4036))) This solves filtering in lisp using association list tools. Common Lisp has its own wildcard stuff #p"foo/*.*" |# (defun do-nothing (s c) " Placed in tmp *readtable* for #\- and #\_ " (declare (ignore c)) (read s t nil t)) (defmacro decode-unix-time (time &aux (fields '(sec min hou day month yea))) " (decode-universal-time (+ time 2208970800)) 2208970800 seconds seem to be the difference. Off by one hour since I made this in daylight savings time." `(multiple-value-bind ,fields (decode-universal-time (+ ,time 2208970800)) (pairlis '(,@fields) ,(append '(list) fields)))) (defmacro comprehend-path-name (name) " (comprehend-namestring name) name is actually the string from (pathname-name path) " `(let ((*readtable* (copy-readtable nil))) (set-macro-character #\- #'do-nothing) (set-macro-character #\_ #'do-nothing) (with-input-from-string (in ,name) (loop for no = (handler-case (read in nil nil) (end-of-file (e) nil)) for field in '(tgid unix-time location? unused index) while no collect `(,field . ,no))))) (defun comprehend-directory (dir &aux (files (directory dir))) (loop for file in files for namestring = (file-namestring file) for path-name = (pathname-name file) for alist = (comprehend-path-name path-name) for time = (decode-unix-time (cdr (assoc 'unix-time alist))) collect (append `((namestring . ,namestring) (decoded-time . ,time)) alist))) (defmacro assoc-filter-dir (dir &rest sexps) (let ((x (gensym)) (time (gensym)) (time-symbols '(sec min month hou day yea))) `(mapcan (lambda (,x) (and ,@(loop for sexp in sexps for modified = (list (cadr sexp) `(cdr (assoc ',(first sexp) ,(if (member (first sexp) time-symbols) `(cdr (assoc 'decoded-time ,x)) x))) (third sexp)) collect modified) (list ,x))) (comprehend-directory ,dir))))