Board logo

标题: [文本处理] 批处理删除重复文件咋写?大小一样,名字相似这种 [打印本页]

作者: allen2023    时间: 2024-10-10 21:24     标题: 批处理删除重复文件咋写?大小一样,名字相似这种

本帖最后由 allen2023 于 2024-10-11 13:24 编辑



如题,删除掉 重复存在的 带(1)的文件,批处理咋写
注意:有的带了(1),但并不重复,不要删除。
作者: 77七    时间: 2024-10-10 22:15

  1. del "*(1).pdf"
复制代码

作者: allen2023    时间: 2024-10-10 22:22

回复 2# 77七

一楼表达不严谨,抱歉。

个别 "*(1).pdf",是独一份的,还不能删除。

豆包生成了个,80那里不会改。
  1. for /r "%dir%" %%F in (*.*) do (
  2.     set "file=%%~nF"
  3.     set "size=%%~zF"
  4.     rem 检查是否已经处理过这个大小的文件
  5.     if defined sizes[!size!] (
  6.         rem 检查文件名相似度
  7.         set "similar=false"
  8.         for %%A in (!sizes[!size!]!) do (
  9.             if "!file!"=="%%~nA" (
  10.                 set "similar=true"
  11.                 goto :skip
  12.             ) else (
  13.                 call :isSimilar "!file!" "%%~nA"
  14.                 if!similarity! geq 80 (
  15.                     set "similar=true"
  16.                     goto :skip
  17.                 )
  18.             )
  19.         )
  20.         if!similar! equ false (
  21.             set "sizes[!size!]=!sizes[!size!]! %%F"
  22.         )
  23.     ) else (
  24.         set "sizes[!size!]=%%F"
  25.     )
  26.     :skip
  27. )
  28. rem 遍历所有大小分组,删除除第一个文件外的其他文件
  29. for /f "tokens=2 delims==" %%A in ('set sizes[') do (
  30.     set "count=0"
  31.     for %%B in (%%A) do (
  32.         if!count! equ 0 (
  33.             set "firstFile=%%B"
  34.         ) else (
  35.             del "%%B"
  36.         )
  37.         set /a count+=1
  38.     )
  39. )
  40. echo Done.
  41. pause
  42. goto :eof
  43. :isSimilar
  44. set "str1=%~1"
  45. set "str2=%~2"
  46. set "similarity=0"
  47. for /l %%I in (1,1,20) do (
  48.     set "char1=!str1:~%%I,1!"
  49.     set "char2=!str2:~%%I,1!"
  50.     if defined char1 if defined char2 (
  51.         if "!char1!"=="!char2!" (
  52.             set /a similarity+=5
  53.         )
  54.     ) else (
  55.         goto :eof
  56.     )
  57. )
  58. goto :eof
复制代码

作者: 77七    时间: 2024-10-10 22:26

回复 3# allen2023


  1. @echo off
  2. cd /d "%~dp0"
  3. for /f "delims=" %%i in ('dir /b /a-d *.pdf ^|findstr /vi "([0-9][0-9]*)\.pdf"') do (
  4. if exist "%%~ni(*).pdf" (
  5. del "%%~ni(*).pdf"
  6. )
  7. )
  8. pause
复制代码

作者: aloha20200628    时间: 2024-10-10 23:50

回复 3# allen2023
  1. @echo off &for /f "delims=(" %%a in ('dir /b/a-d "*(1).pdf" ') do (
  2.      if exist "%%a.pdf" del /q "%%a(1).pdf"
  3. )
  4. pause&exit/b
复制代码

作者: qixiaobin0715    时间: 2024-10-11 08:32

就楼主提供的样本来说,这样简简单单即可:
  1. for %%i in (*.pdf) do if exist "%%~ni(*).pdf" del "%%~ni(*).pdf"
复制代码

作者: allen2023    时间: 2024-10-11 13:30

本帖最后由 allen2023 于 2024-10-11 14:12 编辑

回复 4# 77七


这个或许能解决重复多次的,但有的带了括号但不重复是不能做删除操作的-即2楼补充表达的那个意思(不能伤及无辜 )。
如果文件少,我一个个检查,改掉单独存在的括号文件,用这串代码即可。但多了,肯定是程序执行的更靠谱。

另外,这些文件是在局域网的硬盘里的。执行如下:
  1. UNC 路径不受支持。默认值设为 Windows 目录。
  2. '\\sy\Download\1~9年级典中点\9年级\'
  3. CMD 不支持将 UNC 路径作为当前目录。
  4. 找不到文件
复制代码
再次对您表示感谢!
作者: 77七    时间: 2024-10-11 15:19

回复 7# allen2023


   重新写了代码,调整了代码思路,去除文件末尾"(数字)"并改名,如果已经存在则直接覆盖。支持以下各种情况,支持末尾3位数字以内,支持子目录去重
  1. 苏教版.pdf
  2. 苏教版(1).pdf
  3. 苏教版(1)(1).pdf 执行两次即可
  4. 苏教版(2).pdf
  5. 苏教版(1).pdf
  6. 苏教版(语文).pdf
  7. 苏教版(语文)(1).pdf
复制代码


此为测试版,测试正确,删除 move 前的 echo 再次执行

  1. @echo off
  2. rem 保存为ansi编码
  3. set dirpath=\\sy\Download\
  4. for /f "delims=" %%d in ('dir /b /s /ad "%dirpath%"') do (
  5. echo 目录[%%d]
  6. for /f "delims=" %%i in ('2^>nul dir /b /a-d "%%d\*.pdf" ^| findstr /rie /c:"([0-9][0-9]*)\.pdf" /c:"([0-9][0-9]*)\.pdf"') do (
  7. set filename=%%~ni
  8. set filepath=%%d
  9. echo 文件[%%~nxi]
  10. setlocal enabledelayedexpansion
  11. for /l %%l in (1,1,5) do (
  12. if not defined mo (
  13. if "!filename:~-%%l,1!" equ "(" (
  14. echo move "!filepath!\!filename!%%~xi" "!filepath!\!filename:~0,-%%l!%%~xi"
  15. set mo=1
  16. ) else if "!filename:~-%%l,1!" equ "(" (
  17. echo move "!filepath!\!filename!%%~xi" "!filepath!\!filename:~0,-%%l!%%~xi"
  18. set mo=1
  19. )
  20. )
  21. )
  22. endlocal
  23. )
  24. )
  25. pause
复制代码

作者: allen2023    时间: 2024-10-11 20:12

回复 8# 77七

很强大了。还差一个文件大小的判断,即名字虽相似但这两文件大小不一致不需要操作。

还有,这个代码好像只能操作到子文件夹,首层文件夹文件没得操作,我新建了个子文件夹测试了,已经很好了,这是我没考虑的意外收获,大佬出品的更通用,慢慢学习。

这是再次用ai生成的,始终无法达到要求。供借鉴,
提问词:有一批文件,要删掉其中大小一样 且以 "("+ 数字 +")"  结尾的重复文件,批处理咋写。
  1. @echo off
  2. setlocal enabledelayedexpansion
  3. rem 设置要处理的目录
  4. set "dir=C:\your_directory"
  5. rem 创建临时文件用于存储要保留的文件路径
  6. set "tempFile=temp.txt"
  7. rem 遍历目录下的所有文件
  8. for /r "%dir%" %%F in (*.*) do (
  9.     set "fileName=%%~nF"
  10.     set "fileSize=%%~zF"
  11.     rem 判断文件名是否以“(数字)”结尾
  12.     if "!fileName:~-2!"==")" (
  13.         set "numStart=0"
  14.         for /l %%i in (1,1,20) do (
  15.             set "char=!fileName:~-%%i,1!"
  16.             if "!char!" geq "0" if "!char!" leq "9" (
  17.                 set /a numStart=%%i
  18.             ) else (
  19.                 goto endLoop
  20.             )
  21.         )
  22.         :endLoop
  23.         if "!fileName:~-numStart,1!"=="(" then (
  24.             rem 查找是否有相同大小且相似文件名但不以“(数字)”结尾的文件
  25.             set "baseFileName=!fileName:~0,-numStart)"
  26.             for /r "%dir%" %%G in ("!baseFileName!*") do (
  27.                 if "%%~nG" neq "!fileName!" then (
  28.                     set "otherSize=%%~zG"
  29.                     if!fileSize! equ!otherSize! then (
  30.                         rem 将不以“(数字)”结尾的文件路径写入临时文件
  31.                         echo %%G>>"%tempFile%"
  32.                         goto :nextFile
  33.                     )
  34.                 )
  35.             )
  36.         )
  37.     )
  38.     :nextFile
  39. )
  40. rem 遍历临时文件,删除对应的重复文件
  41. for /f "delims=" %%A in ('type "%tempFile%"') do (
  42.     for /r "%dir%" %%B in ("*(!fileName:~-2!)*") do (
  43.         if "%%B" neq "%%A" then (
  44.             del "%%B"
  45.         )
  46.     )
  47. )
  48. del "%tempFile%"
  49. echo Done.
  50. pause
复制代码

作者: 77七    时间: 2024-10-11 21:49

回复 9# allen2023


  
  1. @echo off
  2. rem 保存为ansi编码
  3. set dirpath=\\sy\Download\
  4. call :1 "%dirpath%"
  5. for /f "delims=" %%d in ('dir /b /s /ad "%dirpath%"') do (
  6. call :1 "%%d"
  7. )
  8. pause
  9. exit
  10. :1
  11. echo 目录[%~1]
  12. for /f "delims=" %%i in ('2^>nul dir /b /a-d "%~1\*.pdf" ^| findstr /rie /c:".([0-9][0-9]*)\.pdf" /c:".([0-9][0-9]*)\.pdf"') do (
  13. set filename=%%~ni
  14. set filepath=%~1
  15. for /f "delims=" %%j in ("%~1\%%i") do (
  16. set filesize=%%~zj
  17. )
  18. echo 文件[%%~nxi]
  19. setlocal enabledelayedexpansion
  20. for /l %%l in (1,1,5) do (
  21. if not defined mo (
  22. set "str=#!filename:~-%%l,1!"
  23. set "str=!str:(=!"
  24. set "str=!str:(=!"
  25. if "!str!" equ "#" (
  26. for /f "delims=" %%j in ("!filepath!\!filename:~0,-%%l!%%~xi") do (
  27. if "%%~zj" equ "" (
  28. echo move "!filepath!\!filename!%%~xi" "!filepath!\!filename:~0,-%%l!%%~xi"
  29. ) else if "%%~zj" equ "!filesize!" (
  30. echo move "!filepath!\!filename!%%~xi" "!filepath!\!filename:~0,-%%l!%%~xi"
  31. )
  32. )
  33. set mo=1
  34. )
  35. )
  36. )
  37. endlocal
  38. )
  39. exit /b
复制代码
0字节文件则覆盖,非0字节文件大小相同覆盖。
作者: allen2023    时间: 2024-10-11 22:00

回复 8# 77七

终于改的目的达成了。%f1!%取不到size,!f1!行了,绕了好久。
现只能操作指定路径下的子目录,本层目录还是没得法,这门学问不容易记忆啊
  1. if "!filename:~-%%l,1!" equ "(" (
  2. set "f1=!filepath!\!filename!%%~xi"
  3. set "f0=!filepath!\!filename:~0,-%%l!%%~xi"
  4. for %%A in ("!f1!") do (set "f1Size=%%~zA")
  5. for %%A in ("!f0!") do (set "f0Size=%%~zA")
  6. if !f1Size! equ !f0Size! (del "!f1!")
  7. REM move "!filepath!\!filename!%%~xi" "!filepath!\!filename:~0,-%%l!%%~xi"
  8. move "!f1!" "!f0!"
  9. set mo=1
  10. )
复制代码

作者: allen2023    时间: 2024-10-11 22:06

回复 10# 77七

11楼发完,才看到10楼的回复。感谢大佬的回复,该问题解决了
作者: hfxiang    时间: 2024-10-12 16:23

回复 1# allen2023

试试MD5码法,此方法与文件名是否相似无关
  1. @echo off&cd /d "%~dp0"
  2. rem 建议保存为ANSI编码格式
  3. rem 功能:删除当前文件夹(不含子文件夹)中的pdf重复文件(删除前请备份原文档以防意外)
  4. rem 方法:计算pdf文件MD5码,遇到后出现MD5码重复的文件将被直接删除(不提示,无回显,无法恢复)
  5. setlocal enabledelayedexpansion
  6. for /f "delims==" %%a in ('set exist_ 2^>nul') do set "%%a="
  7. for %%a in (*.pdf) do (
  8. for /f "usebackq" %%z in (`certutil -hashfile "%%~a" MD5^|find /v ":"`) do set "MD5_32=%%z"
  9. if not defined exist_!MD5_32! (
  10. call set "exist_!MD5_32!=True"
  11. ) else (
  12. del /f "%%~a"
  13. )
  14. )
复制代码

作者: czjt1234    时间: 2024-10-12 16:44

回复 13# hfxiang


    这个好
作者: allen2023    时间: 2024-10-12 17:10

本帖最后由 allen2023 于 2024-10-12 17:17 编辑

回复 13# hfxiang
测试了,方法确实好。
顺便发现个问题:即便是大小不一样的文件,md5也会一样,事实上确实还是同一本书(内容还不完全一致,如水印),哪怕是内容有改动。
对md5刷新一下认知。

文件是夸克云盘下载的,客户端不知道为啥会重复下载,所以有个本贴,

文件有点大我上传一部分,选了8个pdf文件供大家研究这种问题
https://www.123684.com/s/Klhmjv-oVKd3?提取码:KrBv
其中:典中点一年级上册语文部编版​教师用书.pdf 两个重名的就是这种情况。

小记:批处理的路径特殊符号太难理解了,
9楼老师从外在路径上解决问题,速度快,想做出通用的,如后缀是“ - 副本”,弄了半天还是失败,见笑。
13楼md5是根本内在的解决,certutil -hashfile 命令 有点耗时,但精准,小问题是,会把带 “副本”“(1)”这种文件留下,删了文件名正常的。
由衷感谢两位大佬的不吝赐教~
作者: 77七    时间: 2024-10-12 17:35

回复 15# allen2023


   http://bbs.bathome.net/redirect.php?goto=findpost&ptid=66982&pid=272644
md5值可能有空格分隔
作者: aloha20200628    时间: 2024-10-12 18:38

回复 9# allen2023

与楼主分享一个版本》
假设当前目录 c:\a 及其子目录 c:\a\b 中有如下一类重复文件,其源文件例如 c:\a\xxx.pdf,与源文件相同主名和文件大小且以'(n)'结尾文件名的文件均为源文件复制品
   ...
   c:\a\xxx.pdf
   c:\a\xxx(1).pdf
   c:\a\xxx(1)(1).pdf
   ...
   c:\a\b\xxx(2).pdf
   c:\a\b\xxx(2)(1).pdf
   ...
在当前目录下运行如下代码,可保留当前目录中的源文件 c:\a\xxx.pdf,但会删除当前目录及其各子目录中符合上述假设条件的源文件复制品
  1. @echo off &for /f "delims=" %%F in (
  2.    'dir /b/s/a-d "*(*).pdf"^|findstr /ie "([0-9]*).pdf" ') do for /f "delims=(" %%a in ("%%F") do (
  3.    if exist "%%~na.pdf" for %%z in ("%%~na.pdf") do if %%~zz equ %%~zF del /q "%%F"
  4. ) 2>nul
  5. pause&exit/b
复制代码





欢迎光临 批处理之家 (http://bbs.bathome.net/) Powered by Discuz! 7.2