需求:
只用cmd命令,将某目录及其子目录下所有文件都加上bak后缀。
分析:
1. “只用cmd命令”,意味着不能使用TC等工具;
2. “将某目录及其子目录下”,意味着要遍历整个目录,dir命令的/S选项,以及for命令的/R选项都有遍历功能;
3. “所有文件”,意味着遍历时不能包括目录,dir /A:-D 可以排除目录,只列出文件;
4. “加上bak后缀”,可以用ren或move命令。
实战一:豪情万丈
按照上面的分析,熟练点的很快能写出:
代码:
for /F %i in (‘dir /A:-D /S /B’) do move %i %i.bak
眨一眼就能看懂的可以跳过下面的段落,直接摁Alt + F4了-.-
不眨眼还看不大懂的不要着急,且听我慢慢道来^o^(为了弄清楚来龙去脉,下面的解释会夹杂原始英文释义)
先解释 “dir /A:-D /S /B”,dir(ectory)命令的作用是
引用:
Displays a list of files and subdirectories in a directory.
DIR [drive:][path][filename] [/A[[:]attributes]] [/b] [/C] [/D] [/L] [/N]
[/O[[:]sortorder]] [/P] [/Q] [/S] [/T[[:]timefield]] [/W] [/X] [/4]
/A(ttribute):D(irectory) 表示只显示属性是目录的项,D前面加个减号-, 表示非,因此/A:-D就是显示所有非目录的项。
/S(ubdirectories), 表示所有子目录和子目录下的文件也都要显示。
/B(are), 表示显示最简单赤裸的信息就可以了,其它冗余信息都不显示。对于dir命令来说,就是只显示长文件名。
好了,说了这么多,其实很简单,dir /A:-D /S /B 的作用就是显示某目录及其子目录下的所有文件列表。可以打开CMD窗口,亲身体验一下(注意别在C盘根目录用这个命令呵,文件太多,会刷半天屏的。若不幸使用,请使劲摁Ctrl + C退出)来看看 move 和 ren(name) 命令. cmd窗口输入move /?,一清二楚:
引用:
Moves files and renames files and directories.
To move one or more files:
MOVE [/Y | /-Y] [drive:][path]filename1[,…] destination
To rename a directory:
MOVE [/Y | /-Y] [drive:][path]dirname1 dirname2
/Y中的Y是Yes,-Y就是No了。如果知道有重名的,但依旧想自动覆盖,就加上/Y选项,这选项和/S(ilence)选项是我最爱用的选项中的两个,谁用谁知道啊。
ren(ame)命令更简洁:
引用:
Renames a file or files.
RENAME [drive:][path]filename1 filename2.
REN [drive:][path]filename1 filename2.
Note that you cannot specify a new drive or path for your destination file.
虽然简洁,但不简单。首先注意上面的cannot,filename2是不能带目录的,就因为这个原因,我更喜欢用move命令来替代rename。
值得提的一点是,cmd下的大部分命令都支持通配符的,因此要给某目录下的文件加bak后缀,只要ren . ..bak就可以了,如果ren支持/S(ubdirectories),那么 ren /S . ..bak 就能解决最开始那个问题,可恨的是rename太简洁了,不支持任何选项-.-接着我们来看看 for /F %i in (‘command’). 用cmd的大都听过这样一句武林秘籍:学会for,cmd就无敌了。for是cmd命令中的九阴真经,此言绝不虚传。我们一起来看看这本威力无穷的经书吧:
代码:
for /? > forhelp.txt
获取经书的办法我一般不告诉其他人,上面的命令据说RP不好时会引入魔道。如果RP好,请憋着激情澎湃的心情,慢慢将经书打开,映入眼帘的是欲练此功……
引用:
Runs a specified command for each file in a set of files.
上面这个官方说明其实有点狭隘,for不仅仅能对文件集操作,只要是某个集(set),for就能遍历处理。
for的基本用法是:
引用:
FOR %variable IN (set) DO command [command-parameters]
详细解释我就不多说了,经书里说得非常清楚。这里稍微解释下几个“特殊”用法:
FOR /D %variable IN (set) DO command [command-parameters]
/D 中的D是Directory, 表示只匹配目录。
FOR /R [[drive:]path] %variable IN (set) DO command [command-parameters]
/R 中的R是Recursive, 表示递归遍历,在这里就是遍历所有子目录。
利用/R遍历选项,对于顶楼问题,我们还可以得到下面这个解决方案:
代码:
for /R %i in (.) do ren %i ..bak
FOR /L %variable IN (start,step,end) DO command [command-parameters]
/L 中的L我找了半天也无法确定是哪个单词,很可能是List。/L的含义倒是很清楚,经书一点都不含糊。
FOR /F [“options”] %variable IN (set) DO command [command-parameters]
/F中的F是File,这是用得最多的也是最复杂同时最有用的一招,经书的解释也很详细了,我想来想去,没想到值得补充的,想说一点的是,/F(ile)和file-set中的File是广义的,for不仅仅用于文件集,所有字符串集其实都可以用for处理。此外,/F选项加上后,(set)可以是普通的file-set,还可以是”string” or ‘command’;如果options中有usebackq,(set)中的表示又略有不同。
其它详细解释,就不多说了,所谓师傅领进门(自诩为师傅,汗一个先,hitme师爷别生气)…..
好,九阴真经阅读完毕,回到我们要讨论的问题。
来看看 for /F in %i (‘dir /A:-D /S /B’) do move %i %i.bak 就很容易懂了,’dir /A:-D /S /B’是命令,得到所有文件列表,for 用来遍历,对于列表中的每一行,存储到 %i 变量,然后执行 move %i %i.bak 重命名,大功告成。
小结:
1. 在实战一中,我们学会了dir、move、rename、for四个命令。
2. 对于顶楼的问题,我们得到了两个解决方案:
方案一:
代码:
for /F %i in (‘dir /A:-D /S /B’) do move %i %i.bak
方案二:
代码:
for /R %i in (.) do ren %i ..bak
实战二:莫撞墙
高高兴兴的把上面的解决方案交给了老板(不仅提供了,而且提供了两个,老板总该满意了吧),谁料屋不漏却遭连环雷,舒舒服服的决定逛会CCF和DRL水区之时,电话铃声大作,老板发火了:“搞什么搞,两个命令运行了,文件后缀一个也没加上,糊弄我是吧,不赶快搞定扣你绩效……”
晕啊,汗都来了,什么破老板,是不是不会开cmd窗口?上面的命令怎么会有错呢?万般无奈,远程协助老板,不运行不知道,一运行也不吓一跳:
引用:
Microsoft Windows XP [Version 5.1.2600]
(C) Copyright 1985-2001 Microsoft Corp.
……
lifesinger@bpwang ~# for /R %i in () do ren %i .bak
lifesinger@bpwang ~# ren c:\2007.05.21 archivies\公司绝密文件005号.doc *.bak
The syntax of the command is incorrect.
lifesinger@bpwang ~# ren c:\2007.05.21 archivies\公司绝密文件007号.doc *.bak
The syntax of the command is incorrect.
……
汗啊,寒窗二十余年,苦练九阴神功,最后居然败在死背四淫贼手上,数千年祖辈留下来的光荣颜面就此毁于一旦,地面无缝我想凿啊,天堂无路我欲飞……
汗流浃背之时,快速搞定:
方案一修正版:
代码:
for /F “tokens=*” %i in (‘dir /A:-D /S /B’) do move “%i” “%i.bak”
注意:必须加上”tokens=*”,否则%i只能取到第一个空格前面的部分。
方案二修正版:
代码:
for /R %i in (.) do ren “%i” “..bak”
小结:死背四(Space)淫贼无处不在,一定要小心小心又小心。
既是总结也是前言:做而后思之,可以为师矣
喜欢折腾Windows系统的,或多或少都接触过dos命令。虽然已经有很多强大易用的GUI程序,但我始终相信,dos命令以其简洁丰富、灵活多高效的特性将会永远存在而且一直被人使用。
cmd命令是dos命令中的基石,如果有精力,我会一并介绍其他dos下常用的命令行小工具,包括for win32版的ls、grep等。这些小工具强大的生命力,时常让我感到惊讶。
打算写的这个实战系列,对自己来说是一个巩固提高的过程,同时很希望这些文章能对大伙的实际工作有所帮助,哪怕能节约你那么一点点时间,那也是我的愿望。
做而后思之,可以为师矣。我相信任何一个人,只要愿意在具体操作之后,去追寻思考为什么,就都可以成为CMD专家。希望我的这篇文章能抛砖引玉^o^
最后很感谢CMD王子hitme以及集百长于一身的高人asap, 从你们的文章以及回复中,受益匪浅 ^o^