设为首页收藏本站

模具家园论坛

 找回密码
 注册成为会员

QQ登录

只需一步,快速开始

搜索
☆☆登录后将不会有弹窗☆☆
ProE教程大全
☆☆CAD联盟(CAD8.NET)☆☆模具家园论坛管理规定ztools 自動標注外挂
智能分析-->自動標注
查看: 443|回复: 7

[原创]:多层子目录内批量文件重命名的方法(利用4种小众语言) [复制链接]

Rank: 2

在线时间
0 小时
家园币
116
贡献
5138
最后登录
2009-12-28
注册时间
2009-12-28
帖子
3029
积分
116
UID
11775
发表于 2010-1-4 07:25:53 |显示全部楼层
利用4种小众语言进行批量多层子目录内文件重命名的方法

(华南理工大学建筑学院  qjchen)

问题的提出:

有一批txt文件(处于c:\a目录及在此内的多层子目录下),名字是1,2,3,4等比较乱的名字,现在希望用每个文本的第三行文字作为文件的新名字。

(这个要求当然可以是其他比较奇特的,修改一下即可)

为了方便测试,放了一个文件在这里,


http://qjchen.googlepages.com/test.ZIP


请解压到c:\a目录下即可。



现在希望用几种小众语言共同试一下,作为自我学习,也希望各位高手指正、精简及告诉多几种语言的写法。



问题的中心:目录的递归查找文件,文件读取,重命名



1a)纯粹的Lisp语言

既然是Lisp版,当然得先用Lisp语言,此处用的是Vlisp,其中借助了John F. Uhden, Cadlantic的程序。由于VLisp本身只提供了少量的目录函数,因此代码比较长。里面涉及了递归定义。



优点:lisp函数就如一个玩具一样,它用很少的语言定义出一栋高楼大厦,给人有很满足的感觉,当有足够多的Lisp函数构建出函数库,照样有强大的功能。当然,AutoLisp语言的强项在于图形方面,用它来作这些也有点难为它。



缺点:vlisp的速度相对其他语言似乎有些慢。



用法:在autocad2000以上加载之后,运行ren即可。



代码:
;;; ========================================================================
;;; Some of the following code are writen by CHEN QING JUN                 ;
;;; Civil engineering Department, South China University of Technology     ;
;;; Purpose: To get a file list of the currrent path                       ;
;;; The platform: Acad2000 and after                                       ;
;;; 2007.02.19                                                             ;
;;;
Http://chenqj.blogspot.com
                                             ;
;;;
Http://autolisper.googlepages.com
                                      ;
;;; ========================================================================
(defun c:ren (/ direc directree x y direcfile)
  (setq direc (getstring "\nc:/a:"))
  (if (= direc "")
    (setq direc "c:/a")
  )
  (setq directree (@Folders direc))
  (foreach x directree
    (setq direcfile (qj-directory-only-files x))
    (foreach y direcfile
      (if (= (vl-filename-extension y) ".txt")
        (rename y)
      )
    )
  )
)
(defun rename (y / path fh newname)
  (setq path (vl-filename-directory y)
        ext (vl-filename-extension y)
  )
  (setq fh (open y "r"))
  (read-line fh)
  (read-line fh)
  (setq newname (strcat path "/" (read-line fh) ext))
  (close fh)
  (vl-file-rename y newname)
)
(defun qj-directory-only-files (path / lst res)
  (setq lst (vl-directory-files path))
  (setq lst (mapcar
              '(lambda (x)
                 (strcat path "/" x)
               )
              lst
            )
  )
  (foreach x lst
    (if (not (vl-file-directory-p x))
      (setq res (append
                  res
                  (list x)
                )
      )
    )
  )
  res
)
;;; ========================================================================
;; given the parent folder as a Path.                                      ;
;; Note that using a path of "" or "." or "\\" will exclude                ;
;; the drive letter.  McNeel's DOSLIB has a DOS_FULLPATH function          ;
;; that can return such folders with drive designations.                   ;
;; (c) John F. Uhden, Cadlantic                                            ;
;;; ========================================================================
(defun @Folders (Path / Folders @Dirs)
  (defun @Dirs (Path / Dir Dirs)
    (and
      (= (type Path) 'STR)
      (or
        (/= (type DOS_FULLPATH) 'EXRXSUBR)
        (setq Path (DOS_FULLPATH Path))
      )
      (if (wcmatch Path ",*/,*\\")
        (setq Dir Path)
        (setq Dir (strcat Path "/"))
      )
      (setq Dirs (vl-directory-files Dir "*.*" -1))
      (setq Folders (cons Path Folders))
      (setq Dirs (vl-remove-if '(lambda (x)
                                  (vl-position x '("." ".."))
                                ) Dirs
                 )
      )
      (mapcar
        '@Dirs
        (mapcar
          '(lambda (x)
             (strcat Dir x)
           )
          Dirs
        )
      )
    )
  )
  (@Dirs Path)
  (reverse Folders)
)




1b)利用doslib程序库

DOSLib, 是一个免费的AutoLISP/Visual Lisp 程序库。它为Autocad提供了各种可供调用的windows操作函数 . 它是用Objectarx编写的AutoCAD应用程序。 DOSLib 通过各种函数扩展了AutoLISP和Visual LISP的编程功能。部分翻译可以见这里:


http://chenqj.blogspot.com/2007/01/doslib-75_27.html




优点:比Lisp的代码要短不少。



缺点:需外挂ARX函数库,对不同版本的arx需要不一样。



用法:对相应的cad版本,加载相应的doslib



代码:
;;; ========================================================================
;;; Some of the following code are writen by CHEN QING JUN                 ;
;;; Civil engineering Department, South China University of Technology     ;
;;; Purpose: To rename a batch of txt files into new name according to the ;
;;;          third line of the text  (Use DOSLIB)                          ;
;;; The platform: Acad2000 and after                                       ;
;;; 2007.02.19                                                             ;
;;;
Http://chenqj.blogspot.com
                                             ;
;;;
Http://autolisper.googlepages.com
                                      ;
;;; ========================================================================
(defun c:ren (/ direc directree x y direcfile fh newname)
  (setq direc (getstring "\nc:/a:"))
  (if (= direc "")
    (setq direc "c:/a")
  )
  (setq directree (dos_dirtree direc))
  (foreach x directree
    (dos_chdir x)
    (setq direcfile (dos_dir))
    (foreach y direcfile
      (if (= (vl-filename-extension y) ".txt")
              (progn
              (setq fh (open y "r"))
          (read-line fh)
          (read-line fh)
          (setq newname (strcat (read-line fh) ".txt"))
          (close fh)
        (dos_rename y newname)
        )
      )
    )
  )
)




2)Python语言

python语言是一种比较新的脚本语言,虽然比较小众,但是也得到越来越多人的应用,个人只学了很少的一部分,感觉其层次清楚,函数库也比较大,语言相对比较灵活,和lisp有点类似,比如list,def,lambda等等都很熟悉。我用的python版本是activepython:
http://www.activestate.com/
,下面的函数walk函数递归调用子程序中的各层文件是参考了
http://www.chinaunix.net/jh/55/574467.html的函数的。




优点:函数库比较多,语言也算比较清晰

缺点:得安装python解释器。



用法:将代码存为.py文件,在activepython里面打开这个文件,按ctrl R运行即可

注意:python的类似progn之类的操作,是用Tab缩进来描述的,每个缩进代表了一个层次,假如下述代码无法工作的话,请把相应的空格改成Tab,两层的为两个Tab





代码:
import os
filedir = "c:\\a"
filenamelist=[]
def visit(arg, dirname, names, flist = filenamelist):
    flist  = [dirname   "\\"   file for file in names]
os.path.walk(filedir, visit, 0)
for y in filenamelist:
    if os.path.isfile(y):
      f=open(y,'r')
      f.seek(0)
      allline=f.readlines()
      thirdline=allline[2]
      lst=os.path.split(y)
      os.chdir(lst[0])
      f.close()
      os.rename(lst[1] , thirdline.replace("\n", " ") '.txt')




3)cmd脚本语言

(这个是修改精品和drl的hitme大侠的,for的用法比较奇怪也非常强大)

cmd脚本其实就是批处理语言,在win2000之后得到很大的增强,有许多不可思议的操作都用短短几行就得到了解决,范例可见
https://www.dream4ever.org/showthread.php?t=75887


第八楼的帖子,相应还有su99和hitme等高手之作



优点:完全只靠系统本身的批处理语言就解决了问题。

缺点:代码的可读性一般,for的用法非常复制,但也非常强大,好好的学习应该可以解决很复杂的问题(听说黑客整天干这种事,咱可没那种能力和野心:)



用法:将代码存为1.bat文件,放到c:\a目录下,双击运行或者cmd命令行下键入1.bat即可



代码:
@echo off
setlocal  ENABLEDELAYEDEXPANSION
for /f "delims=" %%a in ('dir /s/b *.txt') do (
                        for /f "skip=1 tokens=1,2 delims=:" %%i in ('findstr /n "." "%%a"') do (
                                set n=%%j
                                if "%%i"=="3" (
                                ren "%%"da%%"pa%%"nxa" "!n:"0,10!.txt" 2>nul)
                        )
)       
endlocal






4)用Autohotkey语言

Autohotkey是一个系统键盘及鼠标模拟程序,具有强大的自定义功能,完全可以将之作为一个Autocad热键处理程序来运行(与Autohook各有所长),外国网站是在这里


http://www.autohotkey.com/wiki/inde...ing_.26_Parsing


国内也有好些此中高手


http://www.blogcn.com/user48/yonken/index.html


要先安装一个叫autohotkey的软件,下载地址:
http://www.autohotkey.com/


它的作用是这样的,

比如把下面这三句代码,存为一个叫abc.ahk (abc可以任意取),

代码:
F1::^c
F2::^v
Tab::^l


然后,双击这个abc.ahk,那么它将会认为F1是复制,F2是粘贴,在Autocad中,它会认为Tab键就是和F8键一样的正交键。(你可以用它实现很强大的功能吧:0,不过它和autohook还是不一样的,autohook对于定义单键,比如一个按键的,比如a非常有用,而autohotkey还不行)



本来我想编一个ahk文件来实现用autocad的lisp编辑器批量的autolisp程序的代码格式化的,差一点还没有成功,就先编一个这个来测试一下其目录递归功能,发现也很强大。



优点:语言简洁,更有其他强大的功能

缺点:调试不大方便



用法,将这段代码存为1.ahk文件,双击之则完成



代码:
FileList =  ; Initialize to be blank.
Loop, c:\a\*.*,0,1
        FileList = %FileList%%A_LoopFileFullPath%`n
Loop, parse, FileList, `n
{
        FileReadLine, line, %A_LoopField%, 3
        B= %A_LoopField%
        SplitPath, B, name, path
        NewName = %path%\%line%.txt
        FileMove, %A_LoopField%, %NewName%
}




其实高手只要精通一种语言就可以为所欲为了,本人只是得处理非常多的文本文件,因此乱七八糟的学了一点皮毛,特别是语言不熟悉时程序也经常拖沓不已,各位见笑了。



总体的感觉,Lisp最顺手,编的最快。Doslib也很熟眼。Python之前编过一些,改改就成功,但是原来的listdir不能用了之后得google,cmd学的好苦,但感觉到有一片新天地,而autohotkey是为了后面的一些批量导出tecplot图形而学习的。除了lisp,好像速度都比较快。



假如有各种其他的代码,也请不吝指教,谢谢。

Rank: 2

在线时间
0 小时
家园币
113
贡献
5128
最后登录
2009-12-23
注册时间
2009-12-23
帖子
3019
积分
113
UID
11781
发表于 2010-1-4 11:20:23 |显示全部楼层
很实用的函数,提点小建议,

qj-directory-only-files 可以做如下简化

PHP代码:                            [

拷贝到剪切板

]

(defun qj-directory-only-files (path)
??(MAPCAR (FUNCTION (LAMBDA (x) (STRCAT path "/" x)))
??????(VL-DIRECTORY-FILES path nil 1)
??)
)

使用道具 举报

Rank: 2

在线时间
0 小时
家园币
93
贡献
5114
最后登录
2009-12-30
注册时间
2009-12-30
帖子
2989
积分
93
UID
11764
发表于 2010-1-4 15:14:53 |显示全部楼层
谢谢fools兄,我的mapcar和lambda一直用的比较烂,谢谢fools兄精简:)

使用道具 举报

Rank: 2

在线时间
0 小时
家园币
113
贡献
5065
最后登录
2009-12-22
注册时间
2009-12-22
帖子
2996
积分
113
UID
11771
发表于 2010-1-4 19:09:23 |显示全部楼层
hehe ,我只是改了你的VL-DIRECTORY-FILES函数,当最后一个参数取值为1时,只返回文件名,无目录名,和mapcar,lambda无关。不过,如果在循环中使用lambda时,一定要用(function (lambda ...,不要使用'(lambda...,纯lisp时察觉不出两者的区别,编译成vlx或fas速度差别很大。

使用道具 举报

Rank: 2

在线时间
0 小时
家园币
93
贡献
4876
最后登录
2009-12-26
注册时间
2009-12-26
帖子
2885
积分
93
UID
11773
发表于 2010-1-4 23:03:53 |显示全部楼层
snoopychen 真是博学多才啊.佩服

使用道具 举报

Rank: 2

在线时间
0 小时
家园币
128
贡献
5117
最后登录
2009-12-30
注册时间
2009-12-30
帖子
2991
积分
128
UID
11774
发表于 2010-1-5 02:58:23 |显示全部楼层
刀兄过誉了。我的编程水平比较低,杂而不精,远不如刀兄及其他论坛高手之钻研深刻,跟你们学习了许多,非常感谢。



今天我发现了一个更容易的方法,利用我最最最喜欢的total commander,更加简单的完成了这个问题,由于TC和Lisp无关,我就放在这边算数了。


http://chenqj.blogspot.com/2007/02/totalcmdn.html

使用道具 举报

Rank: 2

在线时间
0 小时
家园币
103
贡献
5110
最后登录
2009-12-31
注册时间
2009-12-31
帖子
3021
积分
103
UID
11778
发表于 2010-1-5 06:52:53 |显示全部楼层
回复:
最初由 fools 发布

hehe ,我只是改了你的VL-DIRECTORY-FILES函数,当最后一个参数取值为1时,只返回文件名,无目录名,和mapcar,lambda无关。不过,如果在循环中使用lambda时,一定要用(function (lambda ...,不要使用'(lambda...,纯lisp?..




关于使用function和'的区别,我一直很迷惑,今天看到fools兄的这种说法,特地做了以下的测试程序,编译后并没有发现速度上的差异,是什么原因?

PHP代码:                            [

拷贝到剪切板

]

(defun w2 (pts)
???(repeat 1000 (mapcar (function (lambda (x) (trans x 0 1))) pts))
??)
(defun w1 (pts)
???(repeat 1000 (mapcar '(lambda (x) (trans x 0 1)) pts))
??)

使用道具 举报

Rank: 2

在线时间
0 小时
家园币
92
贡献
5254
最后登录
2009-12-19
注册时间
2009-12-19
帖子
3089
积分
92
UID
11776
发表于 2010-1-5 10:47:23 |显示全部楼层
你可以看一下acad提供的function函数帮助.

纯lisp看不出两者的区别,将下面的代码编译成vlx或fas,或者直接加载附件中的vlx就可以看出function和quote的区别.用function函数,无论是否编译速度一样,而用quote,编译后非常慢.

PHP代码:                            [

拷贝到剪切板

]

(DEFUN c:tmp (/ T0 T1 T2)
??(SETQ t0 (* 86400 (GETVAR "tdusrtimer")))
??(REPEAT 30000 (MAPCAR '(LAMBDA (x) (* x x)) '(1 2 3)))
??(SETQ t1 (* 86400 (GETVAR "tdusrtimer")))
??(REPEAT 30000
????(MAPCAR (FUNCTION (LAMBDA (x) (* x x))) '(1 2 3))
??)
??(SETQ t2 (* 86400 (GETVAR "tdusrtimer")))
??(princ (strcat "\n is " (rtos (- t2 t1) 2 3) " second"))
??(princ (strcat "\n is " (rtos (- t1 t0) 2 3) " second"))
??(princ)
)






我机器上执行的结果是

PHP代码:                            [

拷贝到剪切板

]

is 1.797 second
Quote> is 11.39 second







上传的附件
[table]
  [tr]
    [td]


?
[url=attachment.php?s=

使用道具 举报

您需要登录后才可以回帖 登录 | 注册成为会员

版主申请 | 论坛管理规定 | 收藏本站

本站内容均为会员发表,并不代表本论坛立场,转载时请注明作者和出处!拒绝任何人以任何形式在本论坛发表与中华人民共和国法律相抵触的言论!

本站开启邮件验证,无法通过验证请Email联系: mh85cn@qq.com 或 QQ:119891935    有事没事都可Q我!

Archiver|模具家园论坛 ( 皖ICP备08001089号 )  

GMT+8, 2012-1-28 17:14 , Processed in 0.395723 second(s), 18 queries .

Powered by Discuz! X2 Licensed

© 2001-2011 Comsenz Inc.

回顶部