目前有这样一个需求:
1、若某文件夹下的文件数目少于10时,删除该文件夹;
2、若文件夹下有子文件夹,则优先检测子文件夹:若任意一层子文件夹内的文件数大于等于10,则保留该层子文件夹内的所有文件,并且该文件夹完整路径上所有父文件夹及其内部的所有文件都原封不动;除此之外,若某一层子文件夹内的文件数量少于10,则删除该子文件夹。
**** 友情提示:最优代码见3楼 ****
代码: | @echo off | | set "destination=" | | set "num=10" | | :: 以上两句可指定要处理的路径及文件数量 | | setlocal enabledelayedexpansion | | cd.>remain.txt | | for /f "delims=" %%i in ('dir /ad /b /s "%destination%"^|sort /r 2^>nul') do ( | | set count=0 | | set flag= | | for /f "delims=" %%j in ('dir /a-d /b "%%i" 2^>nul') do ( | | set /a count+=1 | | ) | | if !count! geq %num% ( | | set flag=yes | | ) else ( | | findstr /ic:"%%i\\" remain.txt>nul&&set flag=yes | | ) | | if not defined flag ( | | rd /q /s "%%i" | | ) else ( | | echo "%%i\">>remain.txt | | ) | | ) | | pauseCOPY |
思路:
要用到的重要命令组合为:for+dir+sort+findstr,用到了临时文件。
1、首先,用 dir /ad /b /s 列举指定目录下所有文件夹的完整路径,并用 sort /r 对路径逆序排列;罗列出来的所有路径放入for中处理。值得注意的是,逆序排列至关重要,是这个问题得以顺利解决的关键,所有后续操作都以逆序排列为基础展开;
2、用 dir /a-d /b 检测列举出来的每一个文件夹路径,统计该路径下的文件数量;
3、若某文件夹下的文件数量少于10,则用 rd /s 删除该文件夹;如果文件数量大于等于10,则保留该文件夹,并把该文件夹的完整路径写入临时文件备查;
4、因为所有的操作都是从某一完整路径的最底层进行回溯,所以,上一步中的所有删除操作都是从最底层开始处理的,用 rd /s 不必担心会删掉子目录;后续的处理,都会把当前路径和临时文件中保留的路径进行对比,只要当前路径在保留路径中的某一层上,都会匹配到,从而被忽略掉。
echo "%%i\">>remain.txt之所以要在路径后面加上反斜杠,是为了在 findstr /ic:"%%i\\" remain.txt 的时候,能正确匹配到完整路径,防止出现 findstr /ic:"c:\test" 的时候,匹配到 c:\test123\abc 这样的路径;
当我测试这段代码的最初版本的时候,屡次无法正确执行,但我一直认为我的思路是正确的,只是代码尚有瑕疵罢了。经过反复的跟踪测试,才发现问题出现在findstr上,从而发现了findstr的一个bug:一般而言,用 findstr /c:"str" 语句的时候,我们认为字符串str内的所有特殊字符都已经被转换为普通字符了,但是在这里,当我们用 findstr /ic:"c:\test\" tmp.txt 这样的语句搜索tmp.txt中的内容时,无论tmp.txt中是否有 "c:\test\1"、"c:\test\abc" 这样的字符串,搜索都无法进行下去,表现为光标一直在cmd窗口中闪烁,无法执行下一条命令,解决的办法是在搜索字符串最后再加一条反斜杠,用"\"把"\"转义。由此观之,findstr中用 /c: 参数并不能保证作为搜索内容的字符串都被当做普通字符处理,当"\"位于搜索字符串的最后时,还需要用"\"进行转义。所以,必须使用 findstr /ic:"%%i\\" remain.txt 而不能用 findstr /ic:"%%i\" remain.txt,切记切记。(这个bug在willsort的这篇文章中有提及:[讨论]findstr的命令行分析机制:http://www.cn-dos.net/forum/viewthread.php?tid=21167)
以上代码的原型是下面这个代码: | @echo off | | :: 删除当前目录下所有空文件夹 | | for /f "delims=" %%i in ('dir /ad /b /s^|sort /r 2^>nul') do rd /q "%%i" 2>nul | | pauseCOPY |
这段代码首先逆序排列文件夹路径,保证了从最底层文件夹开始处理,充分利用了当文件夹下有文件时,单独的 rd 不能直接删除文件夹的特性,并充分考虑到了错误信息的屏蔽,没有一条多余的语句,干脆利落,堪称经典。(代码出处: 一个删除当前目录下及其子目录中的空文件夹的批处理:http://bbs.wuyou.com/viewthread.php?tid=88780)
[ 本帖最后由 namejm 于 2010-12-11 23:15 编辑 ] |