[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖

[已解决]批处理命令for列举的项目如何去除重复内容?

本帖最后由 crist 于 2012-8-30 14:43 编辑

代码如下
  1. @echo off
  2. pushd ~dp0
  3. title 还原Skype聊天记录
  4. if not exist "%ProgramFiles%\WinRAR\Rar.exe" goto error0
  5. set winrar=%ProgramFiles%\WinRAR\Rar.exe
  6. if exist "D:\Personal\My Documents\Skype\backup" (
  7. set source=D:\Personal\My Documents\Skype\backup
  8. ) else (
  9. set source=backup
  10. )
  11. :set_id
  12. cls
  13. echo 提示:1.任何时候若需中断操作都可直接关闭本程序窗口
  14. echo       2.备份前请先退出 Skype 程序
  15. echo       3.支持空格路径,不需要双引号
  16. echo.
  17. set "p=%userprofile%\Application Data\skype"
  18. if exist "%p%" (
  19. echo 目标路径下检测到以下 Skype 用户名:
  20. echo.
  21. for /f "delims=" %%a in ('dir /ad /b /s "%p%\chatsync"') do (
  22.    if exist "%%~dpamain.db" if exist "%%~dpaconfig.xml" (
  23.      for %%b in ("%%a\..") do echo %%~nxb
  24.    )
  25. )
  26. ) else (
  27. echo 未检测到任何 Skype 用户记录
  28. echo 备份列表中存在以下用户名:
  29. if exist "%source%\*_*.zip" for /f "delims=_ tokens=1" %%i in ('dir/a/b/o "%source%\*_*.zip"') do echo %%i
  30. )
复制代码
由于备份列表中一个用户存在多个备份文件,因此代码运行后同一个用户名会被列举多次,请问如何让同一个用户名只列举一次呢?

问题已经解决,不过还有很多东西需要慢慢消化,感谢apang大侠的代码以及他耐心的讲解

将下面的代码替换第33行的内容
  1. if exist "%source%\*_*.zip" (
  2.   for /f "delims=_" %%i in ('dir /a-d/b/on "%source%\*_*.zip"') do (
  3.     if not defined .%%i set .%%i=1&echo %%i
  4.   )
  5. )
复制代码

TOP

回复 2# apang


    这代码太神奇了,能讲解一下吗?

TOP

  1. if/?
复制代码

TOP

回复 4# 狗屁不通


    以我的脑袋如果if /?能看懂就不用上网求助大侠了

TOP

回复 5# crist


   
if not defined .%%i set .%%i=1&echo %%i

如果存在%%i 则定义%%i =1并且显示%%i

TOP

2楼未考虑用户名本身包含"_"字符的情况,假设有用户名ab_c,zip文件ab_c_1.zip,列表时会出错。
还是替换第33行的内容,试试:
  1. if exist "%source%\*_*.zip" (
  2.   setlocal enabledelayedexpansion
  3.   for /f "delims=" %%i in ('dir /a-d/b/on "%source%\*_*.zip"') do (
  4.     set "N=%%i"
  5.     for %%j in ("!N:_=" "!") do set "name=!N:_%%~j=!"
  6.     if not defined .!name! set .!name!=1&echo !name!
  7.   )
  8.   endlocal
  9. )
复制代码

TOP

TOP

回复 7# apang


    测试通过,这代理真是博大精深,我是完全看不懂
    谢谢大侠的代码

TOP

回复 6# 狗屁不通


    定义%%i=1,这里的1是用于选择第一个存在的%%i吗?有没有可能存在定义%%i=某个字母而不是某个数字的情况?如果有,那么定义为字母的意思是什么?

TOP

回复 10# crist


    你可以自己改成某个字母试试,然后再回来问。

TOP

回复 9# crist


7#简单解释:

假设有ab_c_1.zip和ab_c_2.zip两个文件

for循环第一次,变量N被赋值为ab_c_1.zip
"!N:_=" "!"是将所有的下划线替换成双引号对(引号中间带空格)
就成这样子:for %%j in ("ab" "c" "1.zip") do set "name=!N:_%%~j=!"
再将字串ab_c_1.zip分别去掉_ab、_c、_1.zip后的结果赋值给变量name
最终name值为ab_c
if not defined .!name! set .!name!=1&echo !name! 意思是:
如果变量.ab_c未定义,将变量.ab_c赋值为1(其它字符也可以的)并显示变量name的值:ab_c
此时变量.ab_c未曾定义,if条件为真,set .!name!=1&echo !name!将被执行

for循环第二次,变量N被赋值为ab_c_2.zip
同1,最终name也被赋值为ab_c
此时变量.ab_c已被定义(前面被赋值为1),if条件为假,set .!name!=1&echo !name!不被执行
ab_c也就不再显示,达到只显示一次的效果

TOP

回复 12# apang



首先我尝试了echo !N!,输出的是ab_c_1.zip,不懂的地方在下面
一个是set "name=!N:_%%~j=!"这句
(我在这行后面加上 &&echo !name! &&echo %%j输出的结果如下
ab_c_1.zip
"ab"
ab_1.zip
"c"
ab_c
"1.zip"
但是我看不懂这段代码是如何实现这个功能的,我被!和%和~等符号搞晕了)

然后通过if not defined .!name! set .!name!=1&echo !name!这段代码输出了以上全部结果中符合实际情况的一个就是ab_c
(为何!name!前面要加.?另外一个比较弱智的疑问是%name%在什么情况下要写成!name!)

TOP

回复 13# crist

好吧,再试着解释下:
  1. @echo off&setlocal enabledelayedexpansion
  2. set N=ab_c_1.zip
  3. for %%j in ("ab" "c" "1.zip") do set "name=!N:_%%~j=!"
  4. echo,!name!&pause
复制代码
for共循环三次:

1.将%%j赋值为"ab",%%~j值为ab,!N:_%%~j=!即!N:_ab=!(将N值中的_ab替换为空)
  因为ab_c_1.zip不包含_ab,所以name值为ab_c_1.zip

2.将%%j赋值为"c",%%~j值为c,!N:_%%~j=!即!N:_c=!(将N值中的字串_c替换为空)
  所以name值为ab_1.zip

3.将%%j赋值为"1.zip",%%~j值为1.zip,!N:_%%~j=!即!N:_1.zip=!(将N值中的_1.zip替换为空)
  所以name值为ab_c

虽然3次循环都set name=..,但name最终取的是for最后一次(第3次)的set name=..的值
这跟set a=1&set a=2&set a=3&echo !a!最后显示的a值为3道理一样

开启变量延迟后,变量引用符%用!替代。也就是说,加上setlocal enabledelayedexpansion语句后,
将%name%改写成!name!

"为何!name!前面要加."?加不加.都可以,只是偶习惯加上了,避免!name!值为空时if语句报错

TOP

本帖最后由 crist 于 2012-8-29 17:22 编辑

回复 14# apang


    渐渐看懂了,唯独开头一句“将%%j赋值为"ab",%%~j值为ab”这句没明白,我试着加入了一句echo %%~j,结果回显是%~j

以上是我echo的位置不对导致回显错误的

后来改成
  1. @echo off&setlocal enabledelayedexpansion
  2. set N=ab_c_1.zip
  3. for %%j in ("ab" "c" "1.zip") do echo %%~j&pause &&set "name=!N:_%%~j=!"
  4. echo,!name!&pause
复制代码
发现%%~j回显确实如您所说

而直接echo %%j则回显内容有双引号"",这是为什么呢?(这个问题会不会太弱?)

TOP

返回列表