tryhi 发表于 2016-3-20 21:19:26

另类高速历遍指定目录下所有子目录[调用系统tree命令]

本帖最后由 tryhi 于 2016-3-27 18:36 编辑

在历遍目录下所有子目录的大部分方法,对于多层大数量的情况一般耗时都非常长,我通过调用CMD下的tree命令来读取,可以极大的提高速度,虽然代码繁琐,但是速度却提高了5倍以上,我历遍了自己的整个C盘只耗时7秒左右
(defun try-tree(pathx / data ff file m m0 n nn path path-lst tem tou tou1 tou2 zhan)
(setq file (vl-filename-mktemp "try.txt"));临时文件名
(command "SHELL"(strcat "tree " "\"" pathx "\" >"file "&echo shop>>"file));生成文件
(while (/= (_read_last file) "shop"));等待文件生成成功
(setq ff (open file "R");读取文件
    data (read-line ff);读取第一行
    tem(substr data 1 2);取得第一个字符
)
(while (/= tem "├");判断是否到了真正开始的位置
    (setq data (read-line ff)tem(substr data 1 2))
)
(setq
    m0 -1;原始级数为-1,第一个目录为0
    path-lst'();存放最终结果
    zhan(list "");栈,修改此处可以加上目录前缀
)
(while data
    (setq tou(try-StringSplit data "├─"));分隔
    (if (= (length tou)1) (setq tou(try-StringSplit data "└─")));
    (if (> (length tou)1)
      (progn
      (setq tou1(try-StringReplace (car tou) "|" "");把目录前面的|替换成两个空格
          tou2 (strcat (cadr tou) "\\"));把目录加上\
      (setq n(strlen tou1);目录前面的空格数量
          m(/ n 4);空格数量除以4=m级数
      )
      (setq path
          (cond
            ((= m m0);跟上一个目录同级
            (setq zhan(cons tou2 (cdr zhan)));删掉栈的第一个后把目录入栈
            (apply 'strcat (reverse zhan));把栈合并成一个字符串
            )
            ((> m m0);级数大于上一个目录
            (setq zhan(cons tou2 zhan);把目录入栈
                m0 m);修改m0的级别
            (apply 'strcat (reverse zhan));合并栈
            )
            ((< m m0);级数小于上一个目录
            (setq nn(- m0 m -1)
            zhan(try-lst-move-head zhan nn);删掉栈的前n+1个
            zhan(cons tou2 zhan);把目录入栈
            m0 m);修改m0的级别
            (apply 'strcat (reverse zhan));合并栈
            )
          ))
      (setq path-lst(cons path path-lst));目录入表
      )
    )
    (setq data (read-line ff));读取下一行
)
(close ff)
(reverse path-lst)
)
;;读取文件的最后一行
(defun _read_last(file / data ff la)
      (setq ff (open file "R"))
      (if ff
                (progn(while (setq data (read-line ff))
                                                (setq la data)
                                        )
                        (close ff))
      )
      la
)
(defun try-StringSplit(str char / a b i )
      (if (= "" char)(_Str2List str)
                (progn
                        (while (setq i(vl-string-search char str))
                              (setq a(substr str 1 i)
                                        b(cons a b)
                                        str(substr str (+ i (strlen char)1)))
                        )
                        (reverse(cons str b))
                )
      )
)
(defun _Str2List(str / a);注:引用73的函数
(setq str(vl-string->list str))
(while
                (if(<(car str)129)
                        (setq a(cons(chr(car str))a)str(cdr str))
                        (setq a(cons(strcat(chr(car str))(chr(cadr str)))a)str(cddr str))))
(reverse a)
)
(defun _Str2List(str / a);注:引用73的函数
(setq str(vl-string->list str))
(while
                (if(<(car str)129)
                        (setq a(cons(chr(car str))a)str(cdr str))
                        (setq a(cons(strcat(chr(car str))(chr(cadr str)))a)str(cddr str))))
(reverse a)
)
(defun try-lst-move-head (lst i)
    (if (<= i 0)lst
      (repeat i (setq lst (cdr lst))))
)
(defun try-StringReplace(str a b)
(if(and(setq 论坛抽风这句代码发不出(= 'str (type str)))
             (apply'and(mapcar'(lambda(x)(=(type x)'str))(setq a(if(=(type a)'list)a(list a)))))
             (apply'and(mapcar'(lambda(x)(=(type x)'str))(setq b(if(=(type b)'list)b(mapcar'(lambda(x)b)a))))))
    (setq str(_strsplit str a nil)
            str(apply'strcat(mapcar'strcat(car str)(mapcar'(lambda(x)(if(=""x)x(nth(vl-position x a)b)))(last str)))))
    str))

(setq lst-path(try-tree "C:\\"))


注:代码跟附件的内容是一样的,不过附件多了一点点注释,不知道为什么,发源码一直提示非法参数,然后我试着把注释删掉一下,就通过了

ou67169488 发表于 2024-3-25 14:25:01

回帖是一种美德!感谢楼主的无私分享 谢谢

pengfei2010 发表于 2017-10-25 19:49:56

回帖是一种美德!感谢楼主的无私分享 谢谢

pengfei2010 发表于 2017-10-4 15:56:16

感谢楼主的无私分享 谢谢

wzg356 发表于 2016-3-21 20:04:06

函数呢?_strsplit

shh1980 发表于 2016-3-21 22:19:34

感谢楼主的无私奉献!好好研究和学习,谢谢!

tryhi 发表于 2016-3-22 10:09:29

wzg356 发表于 2016-3-21 20:04 static/image/common/back.gif
函数呢?_strsplit

不好意思,缺了一个LLSheng_73的函数,主贴已经更新;;超级字符串分割
;;用一个表对字符串进行分割,返回两个表
;;表1:分割后的字符串表
;;表2:被分割的字符串表
;(_STRSPLIT "12+34分隔35-454,22,33-45" '("+""-""*"","";"" ""=""分隔") nil)
;==>(("12" "34" "35" "454" "22" "33" "45") ("+" "分隔" "-" "," "," "-" ""))
(defun _strsplit(str splits f / i a b l );;BY:LLSheng_73
(if f(setq str(vl-list->string(vl-remove 32(vl-string->list str)))))
(while(<""str)
    (if(vl-remove'nil(mapcar'(lambda(x)(vl-string-search x str))splits))
      (setq i(car(vl-sort(vl-remove'nil(mapcar'(lambda(x)(if(setq l(vl-string-search x str))(cons l x)))splits))
                                                                       '(lambda(s1 s2)(<(car s1)(car s2)))))
                                a(cons(substr str 1(car i))a)b(cons(cdr i)b)
                                str(substr str(+(car i)(strlen(cdr i))1)))
      (setq a(cons str a)b(cons "" b)str"")))
(list(reverse a)(reverse b)))

crtrccrt 发表于 2016-3-26 07:49:40

TRY-STRINGREPLACE
函数呢?

tryhi 发表于 2016-3-27 18:37:25

crtrccrt 发表于 2016-3-26 07:49 static/image/common/back.gif
TRY-STRINGREPLACE
函数呢?

论坛抽风,这个函数发不了,最后没办法改了下源码

aihuyujian 发表于 2016-4-5 18:43:33

支持一下 看看

水仙的错 发表于 2016-5-3 14:04:19

这个看看好用不
页: [1] 2
查看完整版本: 另类高速历遍指定目录下所有子目录[调用系统tree命令]