plackowski Posted June 24, 2020 Posted June 24, 2020 I'm using Lee Mac's great DirectoryFiles routine (copied below) to get a list of files in a given root directory. I'd like to stop the recursion prematurely and return nil if there are over 100 files in the list, but the recursion, mapcars, and lambdas are a bit above my head. Any help would be appreciated! ;; Directory Files - Lee Mac ;; Retrieves all files of a specified filetype residing in a directory (and subdirectories) ;; dir - [str] Root directory for which to return filenames ;; typ - [str] Optional filetype filter (DOS pattern) ;; sub - [bol] If T, subdirectories of the root directory are included ;; Returns: [lst] List of files matching the filetype criteria, else nil if none are found (defun LM:directoryfiles ( dir typ sub ) (setq dir (vl-string-right-trim "\\" (vl-string-translate "/" "\\" dir))) (append (mapcar '(lambda ( x ) (strcat dir "\\" x)) (vl-directory-files dir typ 1)) (if sub (apply 'append (mapcar '(lambda ( x ) (if (not (wcmatch x "`.,`.`.")) (LM:directoryfiles (strcat dir "\\" x) typ sub) ) ) (vl-directory-files dir nil -1) ) ) ) ) ) Quote
marko_ribar Posted June 24, 2020 Posted June 24, 2020 (edited) ;; Directory Files - Lee Mac ;; Retrieves all files of a specified filetype residing in a directory (and subdirectories) ;; dir - [str] Root directory for which to return filenames ;; typ - [str] Optional filetype filter (DOS pattern) ;; sub - [bol] If T, subdirectories of the root directory are included ;; Returns: [lst] List of files matching the filetype criteria, else nil if none are found ;; Mod. by M.R. for special purposes... (defun LM:directoryfiles ( dir typ sub ) (setq dir (vl-string-right-trim "\\" (vl-string-translate "/" "\\" dir))) (vl-some '(lambda ( x ) (if (<= (setq k (1+ k)) n) (progn (setq l (append l (list (strcat dir "\\" x)))) nil) t)) (vl-directory-files dir typ 1)) (if (and sub (<= k n)) (mapcar '(lambda ( x ) (if (not (wcmatch x "`.,`.`.")) (LM:directoryfiles (strcat dir "\\" x) typ sub) ) ) (vl-directory-files dir nil -1) ) ) ) ;; Number of files to list - M.R. (defun listfiles ( n dir typ sub / k l ) (setq k 0) (LM:directoryfiles dir typ sub) l ) (setq *l* (listfiles 100 "C:\\" "*.dwg" t)) ;;; *l* is global, so you nil it after you finish with your job... ;;; (length *l*) => 100 or less HTH., M.R. Edited June 25, 2020 by marko_ribar Quote
BIGAL Posted June 25, 2020 Posted June 25, 2020 Both Doslib and Acet have commands and are line entries "Returns the list of files, which match the mask patterns (can contain wildcards)" (setq dwgs (acet-file-dir "*.dwg" 32 "d:\\acadtemp")) ; note 32 is archive Quote
plackowski Posted June 25, 2020 Author Posted June 25, 2020 Unfortunately I don't think either of these methods will solve my problem. To clarify, my intention is to stop the function before it finishes. I'm letting the user supply the path, but if the user accidentally chooses one of our main networks as the path, autoCAD will freeze up as it tries to process all the subdirectories. This is what I'm trying to avoid. Quote
marko_ribar Posted June 25, 2020 Posted June 25, 2020 3 minutes ago, plackowski said: Unfortunately I don't think either of these methods will solve my problem. To clarify, my intention is to stop the function before it finishes. I'm letting the user supply the path, but if the user accidentally chooses one of our main networks as the path, autoCAD will freeze up as it tries to process all the subdirectories. This is what I'm trying to avoid. I think you haven't analyzed my proposal well... You stated that you need to stop search after routine collects up to 100 files... This is exactly what my suggestion does and if and when that limit is reached, recursions and routine finishes... The problem is that when you specify some of root folders it will search sub folders and if there are many empty, it may continue until all processed - you can't avoid search if limit is not reached... Otherwise - if you specify 1 file and direct folder where there is more than 1 file - it will finish in a blink of an eye... So what is that you exactly want : routine that performs ultra fast ( that's not possible ), or routine that does a job that's needed, but at a cost of time consumption... Either way you should consider supplying correct folder path in advance at the very start of process... Quote
ronjonp Posted June 25, 2020 Posted June 25, 2020 2 hours ago, plackowski said: Unfortunately I don't think either of these methods will solve my problem. To clarify, my intention is to stop the function before it finishes. I'm letting the user supply the path, but if the user accidentally chooses one of our main networks as the path, autoCAD will freeze up as it tries to process all the subdirectories. This is what I'm trying to avoid. Why not check the input IE: (setq pth "R:\\") (if (wcmatch pth "@:\\") (alert "You picked the root of a drive!") ;; Else process ) Quote
plackowski Posted June 25, 2020 Author Posted June 25, 2020 Sorry marko_ribar, I didn't have time to fully review your code this morning, and I misunderstood its approach. I managed to get you're code working and it does do what I asked, but unfortunately you're also correct in that it still takes too long to cancel the operation. What if the limit wasn't on the number of files on the list, but instead on the number of recursions? Perhaps if I could stop it after calling the function maybe 30 times? The other problem I've encountered is I can't distinguish between a nil because it couldn't find any files and a nil because it hit the cap. ronjonp, your solution also works, but I'm concerned it may not be restrictive enough. There are plenty of non-root paths that could cause a hang-up. Quote
BIGAL Posted June 26, 2020 Posted June 26, 2020 (edited) For us oldies shell dir *. >dirlst /b /s then read how many lines in dirlst. so if its like 100's don't do. My D Drive has 10300+ Directories if ran on C would be way more. Could just do a read line max 30 if reached (alert "To many directories") Note the dir check is not fast but compared to wading through a drive may be worthwhile. Edited June 26, 2020 by BIGAL Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.