#| Well! This phlog post implements comprehension of the storm radio recordings by jns: gopher://gopher.linkerror.com/0/phlog/2023/20230403 " The filenames start with the talkgroup id followed by the timestamp of the recording. For example: 9021-1680324909_855162500-call_4036.m4a would be tgid: 9021 and timestamp: 1680324909 Standard unix timestamp, you should be able to convert it to human- readable text with the date command, eg: > date -d @1680324909 Fri Mar 31 11:55:09 PM CDT 2023 " And I used macros. Including! In order to be able to READ - and _ I modified the readtable; which clojure says isn't a good idea, so I only modified a local copy of the readtable. Example: Having recordings/9021-1680324909_855162500-call_4036.m4a $ rlwrap ecl -load jns-storm-filenames.lisp > (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 sorting and filtering in lisp using association list tools. Common Lisp has its own directory wildcard stuff #p"foo/*.*" |# (defun do-nothing (s c) " Placed in tmp *readtable* for #\- and #\_ " (read s t nil t)) (defmacro decode-unix-time (time &aux (fields '(sec min hou day mon yea))) " (decode-universal-time (+ time 2208970800)) 2208970800 seconds seem to be the difference. " `(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))) " (comprehend-directory #p\"path/to/files/*.*\") " (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)))