标题: [文件操作] [已解决]批处理怎样靠CRC32校验来删除文件? [打印本页]
作者: necnec1 时间: 2012-12-1 14:26 标题: [已解决]批处理怎样靠CRC32校验来删除文件?
0000aaca 3337424.pdf
0000b4be 2276006.pdf
0000b4c3 2490533.pdf
0000b4c3 543543543543534-----2917205.pdf
0000b9b0 1495391.pdf
0000bf34 2377773.pdf
0000bf34 567676868678-----3015760.pdf
在F盘根目录下有个AA文件夹 里面有300多万个文件 我建了一个文本文件 按照左边是CRC32校验码 右边是文件名的格式
想把左边CRC32校验码是一样的重复文件 提取出来 只保留一组
比如
0000bf34 2377773.pdf
0000bf34 567676868678-----3015760.pdf
这2组 0000bf34出现2次 说明这2个文件是重复的 删除其中一个文件到回收站 千万别彻底删除了 文件我还有用
需要注意的是 文本文件只有CRC校验码和文件名 并没有路径 只能保证文件名不出现重复 文件夹下还有N多的子文件夹
请会的朋友帮忙 谢谢~
作者: ShadowFiend 时间: 2012-12-1 17:26
- @echo off
- md newfolder 2>nul
- set "crc32sum=%~dp0crc32sum.exe"
- set "#tmp=%~dp0#tmp"
-
- cd /d D:\aa
-
- (for /f "delims=" %%i in ('dir /b/a-d') do (
- %crc32sum% %%i
- ))>%#tmp%
-
- for /f "tokens=1,2" %%i in (%#tmp%) do (
- if not defined %%j (
- set %%j=flag
- copy /y "%%i" "%~dp0newfolder"
- )
- )
- del "%#tmp%" /q
- start %~dp0newfolder
- pause
复制代码
需要工具crc32sum.exe
http://code.kliu.org/misc/hashutils/
作者: BAT-VBS 时间: 2012-12-1 20:52
回复 2# ShadowFiend
楼主要求删除到回收站
作者: ShadowFiend 时间: 2012-12-1 21:13
回复 3# BAT-VBS
大概那个意思就行了,那么死板干嘛
作者: BAT-VBS 时间: 2012-12-1 21:17
回复 4# ShadowFiend
这个需要问楼主
删除其中一个文件到回收站 千万别彻底删除了 文件我还有用
作者: necnec1 时间: 2012-12-1 21:26
回复 4# ShadowFiend
回复楼主 你这个批处理貌似从新校验CRC32 我文件有将近300万个 时间太长了
再说 我已经校验好了
0000aaca 3337424.pdf
0000aaca就是3337424.pdf CRC32校验码
我已经放到了一个文本文件里 现在就是要处理这个文本文件
关键就是这个文本文件没有路径 不好删除
我的愿望是先处理这个文本文件 得到重复的文件名 然后遍历文件夹 去删除同名的文件
作者: ShadowFiend 时间: 2012-12-1 22:10
回复 6# necnec1
子文件夹有重名的你也删?300万个文件确认没有重名的?
作者: necnec1 时间: 2012-12-1 22:30
文件名我已经重命名过了 基本可以排除有重名
就是子文件夹有点多
作者: BAT-VBS 时间: 2012-12-1 22:34
回复 6# necnec1 - @echo off
- for /f "tokens=1-2" %%a in (a.txt) do (
- if not defined _%%a (
- set _%%a=1
- ) else (
- echo 删除%%b
- )
- )
- pause
复制代码
是这个意思吗?
作者: necnec1 时间: 2012-12-1 23:04
楼上的代码有那么点意思了 不过还有点问题
删除的内容只在CMD窗口下显示 不能写入到文件
干脆直接把重复的那一行直接删除吧
反正CRC32的校验码都是固定的前8位 只要前8位字符是一样的 重复的行都删除 只保留一行就行了
作者: weichenxiehou 时间: 2012-12-2 10:23
现在的问题是你那些文件不是在同一目录下,这个是比较困难和耗时的部分。
我的想法是:先将要删除的文件名输出到一个文本a.txt,再将所有文件的完整路径输出到一个文本b.txt,然后用findstr根据这两个文件将需要删除的文件的完整路径取到另一个文本c.txt,最后用for/f循环删除所有需要删除的文件,虽然在多数情况下,临时文件是不推荐的,但这种情况下用临时文件应该是比较好的方式。- @echo off
- ::将下一行的crc32.txt替换为实际的文件名
- (for /f "tokens=1*" %%a in (crc32.txt) do (
- if defined %%a (echo,%%b) else set %%a=1
- ))>a.txt
- dir /s /b /a-d>b.txt
- findstr /i /g:a.txt b.txt>c.txt
- for /f "delims=" %%a in (c.txt) do del /a "%%a"
- del a.txt b.txt c.txt
复制代码
将crc32的校验结果文件和本bat文件一起放到要处理的文件夹的顶层目录,然后运行这个批处理即可。
必须满足:
1.校验结果文件格式要工整,每一行第一列必须为校验码,空格或tab后为文件名;
2.任何子目录不能取名为校验结果文件中的任何一个文件名;
作者: BAT-VBS 时间: 2012-12-2 10:30
回复 10# necnec1
加个简单的重定向就行了,这是基础知识。- @echo off
- for /f "tokens=1-2" %%a in (a.txt) do (
- if not defined _%%a (
- set _%%a=1
- ) else (
- >>b.txt echo 删除%%b
- )
- )
- pause
复制代码
作者: BAT-VBS 时间: 2012-12-2 10:36
回复 11# weichenxiehou
这么简单的问题是不用临时文件滴- @echo off
- for /f "tokens=1-2" %%a in (a.txt) do (
- if not defined _%%a (
- set _%%a=1
- ) else (
- for /f "delims=" %%h in ('dir /s /b /a-d %%b') do (
- del /f /a "%%h"
- )
- )
- )
复制代码
作者: weichenxiehou 时间: 2012-12-2 10:59
回复 13# BAT-VBS
如果文件名中有空格怎么办?每一行都dir /s,300万个文件,你可以去试试效率,写批处理并不仅仅是能够实现就好,还需要考虑效率和特殊情况滴。
作者: BAT-VBS 时间: 2012-12-2 11:00
回复 14# weichenxiehou
只有重复的行才会dir /s,至于到底哪个效率高,就只能等楼主的测试结果了。
作者: BAT-VBS 时间: 2012-12-2 11:02
回复 14# weichenxiehou
空格的问题很容易,稍微改改就行了,一行代码都不用增加,看楼主的实际需求了。
作者: ShadowFiend 时间: 2012-12-2 11:52
回复 11# weichenxiehou
支持这种用法和用临时文件。300万不是小数目,考虑到效率问题,用临时文件是正确的选择。而不是所谓的"那么简单"
作者: BAT-VBS 时间: 2012-12-2 12:41
回复 17# ShadowFiend
在得到楼主的测试数据之前,都是瞎猜。
作者: necnec1 时间: 2012-12-2 13:18
BAT-VBS 你这个批处理 我估计了一下 大概要5个小时 太猛了
半个小时 大概才整理出2万左右
我估算了一下 我这个好像总共有20万左右的重复文件
weichenxiehou 的办法貌似没办法进行 先将要删除的文件名输出到一个文本a.txt 我没有办法得到
再将所有文件的完整路径输出到一个文本b.txt 这个可以 我用Everything导出就可以了
还有::将下一行的crc32.txt替换为实际的文件名 这一句 这个CRC32.TXT是个什么东西 和 A.TXT 是什么关系 要这个文件做什么?
作者: weichenxiehou 时间: 2012-12-2 13:39
回复 19# necnec1
擦,lz要不要这么可爱,那些原理是解释我批处理代码的实际运作方式的,不关你的事啊,你不是有一个存放了校验码和文件名的文本吗,把那个crc32.txt改成那个文本的真实名字就可以了。
作者: necnec1 时间: 2012-12-2 13:41
好滴 帅哥 我试试
作者: BAT-VBS 时间: 2012-12-2 14:05
回复 19# necnec1
好的,你先试试11楼的方案,如果仍然太慢的话,我再用另外一个思路帮你写代码。
作者: necnec1 时间: 2012-12-2 19:14
weichenxiehou 你那个批处理不错 就是能稍微改进一下 我刚测试了一下你的批处理 你那个文件删的没影了 能否删除到回收站 重复的文件我还要 还得比对一下
作者: BAT-VBS 时间: 2012-12-2 20:32
回复 23# necnec1
大概需要执行多长时间?
作者: weichenxiehou 时间: 2012-12-2 20:55
回复 23# necnec1
何必删除到回收站那么麻烦,不同的系统回收站的路径还不一样,建立一个备份文件夹,把要删除的文件移动到这里不就行了。- @echo off
- md backup 2>nul
- ::将下一行的crc32.txt替换为实际的文件名
- (for /f "tokens=1*" %%a in (crc32.txt) do (
- if defined %%a (echo,%%b) else set %%a=1
- ))>a.txt
- dir /s /b /a-d>b.txt
- findstr /i /g:a.txt b.txt>c.txt
- for /f "delims=" %%a in (c.txt) do move /y "%%a" backup\
- del a.txt b.txt c.txt
复制代码
作者: necnec1 时间: 2012-12-2 21:01
BAT-VBS 你的批处理 我从中午12点半开始 到下午的6点半 执行了大概6万左右
刚开始速度还没到那种无法忍受的地步 到后来 几乎是越执行越慢 到6点半 果断放弃
如果20万的重复量的话 不知道1天跑不跑的完
作者: necnec1 时间: 2012-12-2 21:04
weichenxiehou的代码 没敢用300万文件试 先用4000左右的文件测试 非常快 用他的批处理 几秒之内搞定 效率不错 打算今晚大规模用
作者: necnec1 时间: 2012-12-2 21:10
300万的PDF文件 数量巨大 本来想用查找重复的软件弄弄 结果动辄就要起码1天的时间 想想放弃了 想走点捷径 看看批处理 貌似没太好的办法 结果用了一个自己都觉得恶心的办法 用WINRAR来提取CRC32的校验码 300万的文件 用了6个小时 还凑合 基本符合预期 配合批处理我估计 应该很快
这些要谢谢BAT-VBS 和weichenxiehou 2个兄弟大力帮忙
作者: namejm 时间: 2012-12-2 22:11
25楼的代码大致能解决问题
但是,如果环境比较复杂的话,还是会误删文件的
问题出在这一句:- findstr /i /g:a.txt b.txt>c.txt
复制代码
因为 findstr 是部分支持正则表达式的
用 /g:a.txt 从a.txt文件中获取到的字符串几乎每行都含有点号,而点号能匹配任意一个字符
形如 1.pdf 的名称是能和 1Xpdf 这样的字符串匹配的
当 b.txt 中字符串的组成规律足够复杂,出错的几率会很高
另外,从a.txt中获取到的字符串,findstr无法限定它们是否位于绝对路径的最后一层,并且不能限定之后是否包含其他字符
搜索 1.pdf 的时候,能匹配到 d:\test\11.pdf ,也能匹配到 d:\test1.pdf\a.pdf
所以,需要对a.txt中的字符串做进一步处理
当 findstr /g:a.txt 的时候,使得那些特殊字符失去正则意义而回归普通字符的含义,且能限定该字符串等于完整路径的最后一层
一个可行的办法是:
把 a.txt 中每行字符的点号用 \. 来替换,行首添加字符 ^ ,行尾添加字符$
需要用 gsed.exe 进行处理
在25楼的基础上修改如下:- @echo off
- md backup 2>nul
- ::将下一行的crc32.txt替换为实际的文件名
- (for /f "tokens=1*" %%a in (crc32.txt) do (
- if defined %%a (echo,%%b) else set %%a=1
- ))>a.txt
- gsed "s/\./\\./g;s/^/\\\\/;s/$/\$/" a.txt>b.txt
- dir /s /b /a-d>c.txt
- findstr /i /g:b.txt c.txt>d.txt
- for /f "delims=" %%a in (d.txt) do move /y "%%a" backup\
- del a.txt b.txt c.txt d.txt
复制代码
gsed 可以去这里下载:http://www.bathome.net/thread-16975-1-1.html
作者: Batcher 时间: 2012-12-2 22:24
在29楼代码的基础上,改用gawk来判断重复文件,提高效率。- @echo off
- md backup 2>nul
- ::将下一行的crc32.txt替换为实际的文件名
- gawk "{a[$1]++;if(a[$1]>1)print $2}" crc32.txt >a.txt
- gsed "s/\./\\./g;s/^/\\\\/;s/$/\$/" a.txt>b.txt
- dir /s /b /a-d>c.txt
- findstr /i /g:b.txt c.txt>d.txt
- for /f "delims=" %%a in (d.txt) do move /y "%%a" backup\
- del a.txt b.txt c.txt d.txt
复制代码
gsed 可以去这里下载:http://www.bathome.net/thread-16975-1-1.html
gawk 可以去这里下载:http://www.bathome.net/thread-1114-1-1.html
作者: weichenxiehou 时间: 2012-12-2 22:36
回复 29# namejm
传说中的前站长namejm居然现身了,罕见罕见!jm一向以严谨著称,见识了。。。
要规避findstr搜索字符串的特殊字符,是不是可以用/l参数?一个文件名包含在另一个文件名中的情况确实需要考虑,惭愧惭愧。。。- @echo off
- md backup 2>nul
- ::将下一行的crc32.txt替换为实际的文件名
- (for /f "tokens=1*" %%a in (crc32.txt) do (
- if defined %%a (echo,\%%b) else set %%a=1
- ))>a.txt
- dir /s /b /a-d>b.txt
- findstr /il /g:a.txt b.txt>c.txt
- for /f "delims=" %%a in (c.txt) do move /y "%%a" backup\
- del a.txt b.txt c.txt
复制代码
作者: cjiabing 时间: 2012-12-2 22:52
300万的文件要累死机器,刚开始很快,后面空间不足了当然慢了,如果有必要可以分成几部分处理。
作者: namejm 时间: 2012-12-2 22:56
呵呵,如果真要提高效率的话
还是建议从获取校验码的那一步做起
用专门的命令行工具来生成含绝对路径的校验文件
剩下的事情就是对生成的校验文件根据验证码进行处理了
可以用专门的命令行工具filemd5.exe或fsum.exe来生成带绝对路径的校验码文件
作者: namejm 时间: 2012-12-2 23:02
回复 31# weichenxiehou
如果只用findstr来做的话,还是需要对a.txt做特殊处理
比如在生成a.txt的时候,在每行行首都添加反斜杠 \
另外,还要给 findstr 添加 /e 参数
这样才能保证获取的字符串被限定在完整路径的最后一层,且等于最后一层的字符串
还需要特别注意的是,在 findstr 之前需要要在a.txt的最后一行添加一个空行
以防止 findstr /e 时不能获取到 a.txt 中的最后一行非空字符串
作者: Batcher 时间: 2012-12-3 00:32
回复 32# cjiabing
你可以分别针对29楼和30楼的代码分析一下,看看哪里会导致空间(假设你指的是内存)问题。
作者: cjiabing 时间: 2012-12-3 20:37
回复 35# Batcher
你显然不知道我回答问题的出发点在那里,我针对的是26楼说的情况,而非29楼和30楼。楼主这么说:
BAT-VBS 你的批处理 我从中午12点半开始 到下午的6点半 执行了大概6万左右
刚开始速度还没到那种无法忍受的地步 到后来 几乎是越执行越慢 到6点半 果断放弃
如果20万的重复量的话 不知道1天跑不跑的完
为什么执行的效率越来越差?我不是从代码执行效率来说的,而仅仅是从电脑使用操作的角度来说的。我只能简单地说内存资源耗尽了,空间不足了,你真要我说个子丑寅卯来我也无能为力了,因为我非计算机专业,仅能从我十年使用电脑的经验做出这样粗浅的判断。
作者: necnec1 时间: 2012-12-4 00:51
weichenxiehou最后的代码 出现了和BAT-VBS 类似的瓶颈 都是6个多小时查找到6万左右 跑起来相当费力 CPU占用50% 内存只耗费不到19M 感觉不像是内存的问题 我是2G的内存 5300的U 应该还凑合吧
是不是CMD本身的限制
namejm 版主改写的批处理貌似运行了一闪而过 只有一个backup文件夹 里面没东西 软件也下了 是哪有问题?
作者: necnec1 时间: 2012-12-4 00:57
我现在是这么一个想法
文本文件A 内容如下
3eb27c6f 8026844.pdf
e259ce1a 8026845.pdf
e259ce1a 8026644.pdf
d85ec019 8026847.pdf
e84f9de0 8026848.pdf
我再弄一个文本文件B 将所有PDF的完整路径和名称用Everything导出来
用文本文件A 和文本文件B去做比较 得出重复文件的完整路径和名称 然后转移保存到文件夹 岂不是更快
作者: Batcher 时间: 2012-12-4 12:10
回复 37# necnec1
不要双击运行。打开一个CMD窗口,去运行那个bat文件,看看报错信息是什么。
作者: Batcher 时间: 2012-12-4 12:10
回复 36# cjiabing
从37楼来看,不是内存问题。
作者: weichenxiehou 时间: 2012-12-4 20:38
本帖最后由 weichenxiehou 于 2012-12-4 20:46 编辑
回复 37# necnec1
我估计是因为用set定义了太多的变量,后面用if defined在如此之多的变量里面查找会比较吃力,可以先用sort排序,然后用一个变量来比较。- @echo off&setlocal enabledelayedexpansion
- md backup 2>nul
- ::将下一行的crc32.txt替换为实际的文件名
- (for /f "tokens=1*" %%a in ('sort crc32.txt') do (
- if %%a=="!str!" (echo,\%%b)
- set "str=%%a"
- ))>a.txt
- dir /s /b /a-d>b.txt
- findstr /ile /g:a.txt b.txt>c.txt
- for /f "delims=" %%a in (c.txt) do move /y "%%a" backup\
- del a.txt b.txt c.txt
复制代码
亲测,a.txt不额外加一空行不会出现jm说的最后一行不会当成搜索字符串的问题。
作者: BAT-VBS 时间: 2012-12-5 11:46
回复 41# weichenxiehou
是不是你用的操作系统跟他的不一样啊?是XP吗,还是Win7啊?
作者: weichenxiehou 时间: 2012-12-5 19:09
回复 42# BAT-VBS
“他”是指谁?namejm?我用的win7,难道xp下面必须要在最后加空行,不知,我最开始用电脑就是从win7开始的。
欢迎光临 批处理之家 (http://bbs.bathome.net/) |
Powered by Discuz! 7.2 |