Board logo

标题: [文件操作] 如何分别删除所有子文件夹下同名文件中除了数字序号最大的一个文件外的所有其他文件 [打印本页]

作者: awei    时间: 2015-1-9 14:07     标题: 如何分别删除所有子文件夹下同名文件中除了数字序号最大的一个文件外的所有其他文件

本帖最后由 pcl_test 于 2016-11-16 18:03 编辑

现在有很多软件操作,每保存一次文件,就会重新生成一个新的文件,文件名是一样的,但是,在后缀后面会自动增加一个数字序号,用来表示此文件的修改版本

往往文件完成后,会产生大量的前期版本文件,求一个一次性操作删除旧版本文件的BAT。

如:*.jpg.1 *.jpg.2 *.jpg.3 *.bmp.1 *.bmp.2 *.bmp.3 *.gif.1 *.gif.2 *.gif.3 ........

执行批处理后,所有文件夹及子文件夹,只保留最后的一个版本的文件,如*.jpg.3 *.bmp.3 *.gif.3

如果,文件夹中只有一个文件,同样保留,如,只有*.jpg.1,那么,保留。

但是,删除文件的提前是只在当前文件夹中作比较,也就是说,在不同的文件夹中,可能会有同名文件,不作统一的比较,只在本文件夹中保留同名文件的最后一个版本。

也就是说:

1.各个文件夹相对独立,不和其它文件夹作比较

2.相同文件夹下的不同格式及不同名称文件,不和其它格式及不同名称文件作比较,即00.jpg.*不会和00.bmp.*不会和00.gif.*作比较

谢谢~!
作者: pcl_test    时间: 2015-1-9 19:12

回复 1# awei

  1. @echo off
  2. set n=0
  3. for /f "delims=" %%i in ('dir /a-d /b "E:\test\"') do (
  4. set /a n+=1
  5. )
  6. for /f "tokens=1-3 delims=." %%a in ('dir /a-d /b "E:\test\"') do (
  7. if %%c lss %n% (del "E:\test\%%a.%%b.%%c" /f /q)
  8. )
  9. pause
复制代码

作者: 545810831    时间: 2015-1-9 21:51

本帖最后由 545810831 于 2015-1-9 22:13 编辑
  1. @echo off
  2. setlocal enabledelayedexpansion
  3. for /f "delims=" %%i  in ('dir /b  *.jpg*') do (
  4. set /a m+=1
  5. set a=%%~xi
  6. set _!m!=!a:.=!
  7. )
  8. set max=0
  9. :stat
  10. set /a d+=1
  11. if  !_%d%! gtr !max! (
  12. set max=!_%d%!
  13. )
  14. if %d% lss !m! goto stat
  15. echo !max!
  16. for /f "delims=" %%i  in ('dir /b  *.jpg*') do (
  17. set a=%%~xi
  18. set k=!a:.=!
  19. if !k! lss !max! del "%%i"
  20. )
  21. pause
复制代码

作者: awei    时间: 2015-1-10 08:22

首先非常感谢2楼和3楼的兄弟,谢谢~!!!

我赶紧试试先
作者: awei    时间: 2015-1-10 08:34

回复 2# pcl_test


    感谢兄弟~!

    不过,我刚才在试验的时候,将E:\test\替换成存放BAT的目录,运行后,发现了两个问题:

1.当前文件夹内,除了子文件夹外,所有文件都删除了,包括bAT本身。

2.子文件夹下的文件依然存在,没有变动。
作者: awei    时间: 2015-1-10 08:36

回复 3# 545810831


    感谢这位兄弟~!

第一时间试验了下也发现了一个问题:

BAT只作用在当前的文件夹,子文件夹同样是没有变动。

我是希望所有的子文件夹都有同样的作用,谢谢~!
作者: awei    时间: 2015-1-10 08:42

本帖最后由 awei 于 2015-1-10 08:45 编辑

补充说明:

同时删除多个不同格式的文件,如*.jpg  *.bmp

弱弱问,是不是可以用逗号来分开?

如:

将('dir /b  *.jpg*')

改成('dir /b *.jpg,.bmp*‘)

谢谢~!
作者: awei    时间: 2015-1-10 08:54

回复 3# 545810831


    我自己试了,还不会弄直接删除多个不同格式的文件。求教~!

我将:('dir /b *.jpg*')
改成:('dir /b /s *.jpg*') ,实现了作用于所有子文件夹的功能。
作者: 慕夜蓝化    时间: 2015-1-10 09:04

回复 8# awei


dir /s/b/aa *.jpg
列出当前文件夹下的所有jgp格式的文件,包括子目录中的文件

你再详细说明一下你的问题。
作者: awei    时间: 2015-1-10 09:21

本帖最后由 awei 于 2015-1-10 09:24 编辑

回复 9# 慕夜蓝化


    我是文件夹中有多种格式的文件,但,它们都是在后缀的最后会加上.1 .2 .3 ...这样的序号,如:*.jpg.1 *.jpg.2    *.bmp.1 *.bmp.2 .......

   我在执行BAT时,希望只保留这些不同文件的最后一个,3楼的大神已经帮我实现了,只是,他只写了删除一种格式文件的,但我不会修改,请帮忙,谢谢~!
作者: awei    时间: 2015-1-10 09:33

回复 9# 慕夜蓝化


    谢谢你,我已经自己摸索出来了,加空格键就可以了,谢谢~!

如:('dir /b /s *.jpg* *.bmp*')
作者: awei    时间: 2015-1-10 09:40

再次感谢:

2# pcl_test     

3# 545810831         

9# 慕夜蓝化
作者: 慕夜蓝化    时间: 2015-1-10 10:11

回复 10# awei
  1. @echo off
  2. setlocal enabledelayedexpansion
  3. for /f "delims=" %%i in ('dir /s/b/ad') do (
  4.     pushd "%%~fsi"&call :a "*.jpg*" "*.bmp*"
  5. )
  6. pause&exit
  7. :a
  8. if not "%~1"=="" (
  9.     shift
  10.     for /f "tokens=*" %%a in ('dir /b/a-d/o-d %~1') do (
  11.                 set/a n+=1
  12.                 if not !n! equ 1 del /q "%%~fsa"
  13.                 )
  14.     set "n="
  15.     goto :a
  16.         ) else (
  17.     goto :eof
  18. )
复制代码
删除除最新生成文件以外的所有文件, 你可以先试用一下,我这里测试可以。
作者: awei    时间: 2015-1-10 10:18

各位大神,发现了一个问题:

这个检测功能存在一个全局性,如果我的各种格式文件中,有一个的后缀序号比较大,那么,执行程序后,所有文件夹中的文件都删除了,只保留下这个最大序号的文件了。。。。

如多个子文件夹里都存在:*.jpg.1 *.jpg.2 *.jpg.80 *.bmp.1 *.bmp.2

执行BAT后:所有文件夹都只保留了*.jpg.80这么一个文件了,连*.bmp文件也没有了。

如果多种格式的后缀最大序号相同,那么,都保留了。

如有*.jpg.80和*.bmp.80,那么,其它文件全删,保留这两个最大的。

求完善,谢谢~!
作者: awei    时间: 2015-1-10 10:26

回复 13# 慕夜蓝化


    也可以说是删除最新文件以外的文件,

   但,需要多种不同格式文件并存,

  也就是说,这个“最新”只针对同一个文件名的文件

如:*.jpg.1 *.jpg.2 *.jpg.80 *.jpg.521   *.bmp.3 *.bmp.8 *.bmp.120 *.bmp.421 *.bmp.550 *.gif.20 *.gif.35 *.gif.45 *.gif.222

执行BAT后,保留:

*.jpg.521  *.bmp.550  *.gif.222

如果能实现  在识别序号的基础上   再针对相同文件名的文件作时间上的对比,优先保留最新时间的文件,则更加的理想。谢谢~!
作者: 慕夜蓝化    时间: 2015-1-10 10:38

回复 15# awei [/b

嗯嗯,那么就需要检测当前文件夹下共有哪种格式的文件了,不过,你的这个文件名后缀并不合法;
建议你这样,如果文件夹下的几种格式不是特别多,能够列出来的话
比如  *.jpg* *.bmp* *.gif* 等。
你看到上面发的那串代码了吗
你只要在:
  1. pushd "%%~fsi"&call :a "*.jpg*" "*.bmp*" "*.gif*"
复制代码
添加你想要删除的扩展名格式就行了。注意,中间有一个空格,你可以测试一下,应该会符合的你的要求。
作者: xxpinqz    时间: 2015-1-10 12:54

自己复制一些文件测试下:
  1. @echo off&setlocal enabledelayedexpansion
  2. set ext="*.jpg.* *.bmp.*"
  3. (for /f "delims=" %%a in ('dir /b/s "%ext%"^|findstr /e ".[0-9]"') do (
  4.       set "str=000000%%~xa"
  5.       echo,%%~dpna/!str:~-8!
  6. ))>tmp
  7. for /f "tokens=1-2 delims=/" %%a in ('sort tmp') do (
  8.     if "%%a"=="!file!" (
  9.     del /q "%%a%%~xb"
  10.     ) else (
  11.         set "file=%%a"
  12.     )
  13. )
  14. del tmp
复制代码

作者: awei    时间: 2015-1-10 13:57

回复 16# 慕夜蓝化


    试过了你的代码,发现如下问题:

1.当前文件夹文件没有删除,只作用于子文件夹

2.同时存在两种不同格式文件时,会作出比较,然后保留了相同序号的文件,这是其中一个格式有用,另一个却又无效。

3.相同的几个文件,继续执行BAT,则保留了相同的小序号的文件,大的序号则删除了。
作者: awei    时间: 2015-1-10 14:02

本帖最后由 awei 于 2015-1-10 14:22 编辑

回复 17# xxpinqz


    测试过后,发现了两个问题:

1.后缀最大序号为82

如果小于82的序号,则可以实现功能

如果大于82,则会被删除。

通常来说,这个序号是可以无限大的,但,由于经常性的清理旧版本文件,所以,这个数一般也不会太过离谱,但,在三五千以下就比较保险了。^-^

2.各种文件(我测试了三种,而且,我至少需要三种),会按照其中序号相同的来排序,而且是保留序号小的文件,其它文件都删除


请大神修正,谢谢~!
作者: awei    时间: 2015-1-10 14:36

回复 17# xxpinqz
回复 2# pcl_test
回复 3# 545810831
回复 13# 慕夜蓝化

    我修改了规则,前面说得不够清晰,抱歉:

现在有很多软件操作,每保存一次文件,就会重新生成一个新的文件,文件名是一样的,但是,在后缀后面会自动增加一个数字序号,用来表示此文件的修改版本

往往文件完成后,会产生大量的前期版本文件,求一个一次性操作删除旧版本文件的BAT。

如:*.jpg.1 *.jpg.2 *.jpg.3 *.bmp.1 *.bmp.2 *.bmp.3 *.gif.1 *.gif.2 *.gif.3 ........

执行批处理后,所有文件夹及子文件夹,只保留最后的一个版本的文件,如*.jpg.3 *.bmp.3 *.gif.3

如果,文件夹中只有一个文件,同样保留,如,只有*.jpg.1,那么,保留。

但是,删除文件的提前是只在当前文件夹中作比较,也就是说,在不同的文件夹中,可能会有同名文件,不作统一的比较,只在本文件夹中保留同名文件的最后一个版本。

也就是说:

1.各个文件夹相对独立,不和其它文件夹作比较

2.相同文件夹下的不同格式及不同名称文件,不和其它格式及不同名称文件作比较,即00.jpg.*不会和00.bmp.*不会和00.gif.*作比较

谢谢~!
作者: apang    时间: 2015-1-10 14:38

本帖最后由 apang 于 2015-1-10 14:51 编辑

如果回显结果正确,删除第3行的 echo
  1. @set @n=0;/* & echo off
  2. for /f "tokens=1*" %%a in ('dir /b^|cscript -nologo -e:jscript "%~0"') do (
  3.         echo,Del "%%b"
  4. )
  5. pause & exit/b & rem */
  6. dic = new ActiveXObject("Scripting.Dictionary");
  7. while (!WScript.StdIn.AtEndOfStream) {
  8.         f = WScript.StdIn.ReadLine();
  9.         m = f.match(/.+\.(.+?)\.(\d+)$/);
  10.         if (m) {
  11.                 k = m[1].toLowerCase();
  12.                 m[2] = ("0000000000" + m[2]).substr(m[2].length);
  13.                 if (dic.Exists(k)) {
  14.                         dic.Item(k) += "\n" + m[2] + " " + m[0];
  15.                 } else dic.Add(k, m[2] + " " + m[0])
  16.         }
  17. }
  18. arr = (new VBArray(dic.Keys())).toArray();
  19. for (i=0; i<arr.length; i++) {
  20.         a = dic(arr[i]).split("\n").sort().slice(0, -1);
  21.         WScript.Echo(a.join("\n"))
  22. }
复制代码

作者: awei    时间: 2015-1-10 15:09

回复 21# apang


    测试过发现两个问题:

1.只作用于当前文件夹,无法作用子文件夹

2.自动检测后缀功能非常好,不过,似乎有点乱,相同后缀,但不同名称的文件,只保留了其中之一,而且不固定是哪一个。
作者: apang    时间: 2015-1-10 15:51

本帖最后由 apang 于 2015-1-10 16:39 编辑

回复 22# awei


    试试:
  1. @set @n=0;/* & echo off
  2. set "Js=cscript -nologo -e:jscript"
  3. pushd "D:\Test\"
  4. for /f "tokens=1*" %%a in ('dir /a-d /b /s ^| %Js% "%~0"') do (
  5.         echo,Del "%%b"
  6. )
  7. pause & exit/b & rem */
  8. dic = new ActiveXObject("Scripting.Dictionary");
  9. while (!WScript.StdIn.AtEndOfStream) {
  10.         f = WScript.StdIn.ReadLine();
  11.         m = f.match(/(.+\..+?)\.(\d+)$/);
  12.         if (m) {
  13.                 k = (m[1]).toLowerCase();
  14.                 m[2] = ("000000000000" + m[2]).substr(m[2].length);
  15.                 if (dic.Exists(k)) {
  16.                         dic.Item(k) += "\n" + m[2] + " " + m[0];
  17.                 } else dic.Add(k, m[2] + " " + m[0])
  18.         }
  19. }
  20. arr = (new VBArray(dic.Keys())).toArray();
  21. for (i=0; i<arr.length; i++) {
  22.         a = dic(arr[i]).split("\n");
  23.         if (a.length > 1) {
  24.                 WScript.Echo(a.sort().slice(0, -1).join("\n"))
  25.         }
  26. }
复制代码

作者: awei    时间: 2015-1-10 16:11

回复 23# apang


    DOS界面第一句提示系统找不到路径,然后下面则是显示删除的文件清单,但是,退出后,文件并没有被删除,同时也不作用于子文件夹。谢谢~!
作者: apang    时间: 2015-1-10 16:19

回复 24# awei


    第3行路径改成实际路径
作者: awei    时间: 2015-1-10 16:47

回复 25# apang


    嗯,一开始没注意到有个路径,不过,还是没有删除文件,虽然有显示。
作者: apang    时间: 2015-1-10 17:26

回复 26# awei


    显示结果正确不?
正确的话,删掉多余的echo, 再次运行即可
作者: awei    时间: 2015-1-10 17:31

回复 27# apang


    嗯嗯,可以,暂时没有发现错误,请加上同时子文件夹的功能,谢谢~!周末愉快~!!!
作者: apang    时间: 2015-1-10 18:23

回复 28# awei


    Microsoft Windows [版本 6.1.7601]
版权所有 (c) 2009 Microsoft Corporation。保留所有权利

C:\Windows\System32>cd /d D:\Test\

D:\Test>dir /b/s | findstr \.[0-9][0-9]*$
D:\Test\new.JPG.1
D:\Test\new.doc.11
D:\Test\file2.txt.12
D:\Test\new.doc.100
D:\Test\new.jpg.21
D:\Test\file2.txt.2
D:\Test\new.jpg.25
D:\Test\b.txt.1
D:\Test\abc\NEW.JPG.1
D:\Test\abc\new.DOC.1
D:\Test\abc\new.jpg.99
D:\Test\abc\new.doc.100
D:\Test\abc\new.jpg.10

D:\Test>Test.bat
Del "D:\Test\new.JPG.1"
Del "D:\Test\new.jpg.21"
Del "D:\Test\new.doc.11"
Del "D:\Test\file2.txt.2"
Del "D:\Test\abc\NEW.JPG.1"
Del "D:\Test\abc\new.jpg.10"
Del "D:\Test\abc\new.DOC.1"
请按任意键继续. . .


亲测,处理子文件夹没有问题
作者: pcl_test    时间: 2015-1-10 21:55

回复  apang


    嗯嗯,可以,暂时没有发现错误,请加上同时子文件夹的功能,谢谢~!周末愉快~!! ...
awei 发表于 2015-1-10 17:31


把apang在23楼的代码稍微改下即可
  1. @set @n=0;/* & echo off
  2. set "Js=cscript -nologo -e:jscript"
  3. ::自行更换成实际路径
  4. pushd "E:\Test\"
  5. for /f "tokens=1*" %%a in ('dir /a-d /b /s ^| %Js% "%~0"') do (
  6.         echo,删除文件"%%b"
  7.         Del "%%b" /f /q
  8. )
  9. pause & exit/b & rem */
  10. dic = new ActiveXObject("Scripting.Dictionary");
  11. while (!WScript.StdIn.AtEndOfStream) {
  12.         f = WScript.StdIn.ReadLine();
  13.         m = f.match(/(.+\..+?)\.(\d+)$/);
  14.         if (m) {
  15.                 k = (m[1]).toLowerCase();
  16.                 m[2] = ("000000000000" + m[2]).substr(m[2].length);
  17.                 if (dic.Exists(k)) {
  18.                         dic.Item(k) += "\n" + m[2] + " " + m[0];
  19.                 } else dic.Add(k, m[2] + " " + m[0])
  20.         }
  21. }
  22. arr = (new VBArray(dic.Keys())).toArray();
  23. for (i=0; i<arr.length; i++) {
  24.         a = dic(arr[i]).split("\n");
  25.         if (a.length > 1) {
  26.                 WScript.Echo(a.sort().slice(0, -1).join("\n"))
  27.         }
  28. }
复制代码

作者: awei    时间: 2015-1-11 08:56

回复 29# apang
回复 30# pcl_test

谢谢大神们!今天休息了,没有电脑测试,抱歉了,明天第一时间来测试!祝你们周末愉快!!!
作者: apang    时间: 2015-1-11 13:50

其实,17楼 xxpinqz 的思路非常不错,只是楼主不识货。
小改一下 :
  1. @echo off & setlocal enabledelayedexpansion
  2. pushd "D:\test\"
  3. if "%1" == "OK" (
  4.     for /f "delims=" %%a in ('dir /b/s^|findstr \.[0-9][0-9]*$') do (
  5.         set "str=0000000000%%~xa"
  6.         set "str=!str:.=!"
  7.         echo,%%~dpna/!str:~-10!%%~xa
  8.     )
  9. ) else (
  10.     for /f "tokens=1*delims=/" %%a in ('"%~0" OK^|sort /r') do (
  11.         if /i "%%a" == "!file!" (
  12.             echo Del "%%a%%~xb"
  13.         ) else set "file=%%a"
  14.     )
  15.     pause
  16. )
复制代码

作者: awei    时间: 2015-1-12 09:49

回复 32# apang


    大神,实在是惭愧呀,我是完全不懂的外行,谢谢你们~!




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