Board logo

标题: [文本处理] 批处理如何用dir命令列磁盘文件时排除一个或多个文件夹? [打印本页]

作者: newfish    时间: 2011-8-4 17:41     标题: 批处理如何用dir命令列磁盘文件时排除一个或多个文件夹?

dir c:\  /b | findstr /v /x "WINDOWS"
这句可以排除WINDOWS目录(WINDOWS必须为大写)

可是加/s参数  dir /s c:\  /b | findstr /v /x "WINDOWS"  就不行 。。

我修改代码如下报错 此时不应有 “|”
for /f %%i in ('dir c:\  /b | findstr /v /x "WINDOWS"') do ('dir /s c:\%%i >1.txt')

问题:
如何用dir /s 列磁盘文件的时侯,排除一个或多个文件夹
作者: CrLf    时间: 2011-8-4 17:45

这里的 | 需要转义:
  1. for /f %%i in ('dir c:\  /b ^| findstr /v /x "WINDOWS"') do ('dir /s c:\%%i >1.txt')
复制代码
或者
  1. for /f %%i in ('"dir c:\  /b | findstr /v /x "WINDOWS""') do ('dir /s c:\%%i >1.txt')
复制代码

作者: newfish    时间: 2011-8-4 17:47

原来如此 ..感谢版主!  in 里面的 应当是文本来处理来着...明白了 !!!
作者: CrLf    时间: 2011-8-4 17:52

不是当文本处理,而是作为参数传递给新的 cmd 进程,以下解释转自批处理吧:
for /f 从命令获取输入时,将启用新的 cmd 进程来解释执行 '号对之间的内容,也就是要经历两次预处理,在 for 中一次、cmd 中又一次,而这些内容中若包含特殊字符,将导致for命令被错误划分。

那行代码执行时,dir /b /ad /s c:\^|sort /r 将作为 cmd /c 的参数执行,也就是 cmd /c dir /b /ad /s c:\^|sort /r,| 在第一次预处理中被转义为普通字符,到了新的 cmd 进程中才起到了管道符应有的作用。

当然,同样可以用双引号来转义整个参数,而无需挨个转义所有特殊字符——既然 cmd /c "dir /b /ad /s c:\|sort /r" 成立,那同样可以在 for /f 中这么做,所以这样写也是可以的:for /f "delims=" %%a in ('"dir /b /ad /s c:\|sort /r"') do rd /q %%a 2>nul

顺便说一下,因为 for /f 从命令获取输入时是从新的 cmd 进程中获取其输出,这些输入的信息在被读取之前都是停留在内存中的,所以其效率不如将输入重定向到文本、再用 for /f 从文件获取输入来得高,不过具体情况具体分析,并无所谓哪种方法一定是最好的。另外,这不宜在循环中使用,因为那将循环开启新的 cmd,效率等同于重复循环使用 findstr、sort 等外部命令。

作者: newfish    时间: 2011-8-4 18:22

本帖最后由 newfish 于 2011-8-4 18:31 编辑

这段代码 总感觉鸡肋 的很.
鸡肋的原因
dir/s 会连带之前 dir 出来的文件   也就是会出现  dir /s c:\123.txt  但是在最后输出的时候并不能看到这些文件名,,特别苦恼!
求解决办法!
别且罗列出来的是追加出来的那种 和本身的 dir/s 输出的格式有出入 ~~~郁闷
作者: CrLf    时间: 2011-8-4 18:37

回复 5# newfish


    不明白,可否检查一下 %dircmd% 是否为空
作者: newfish    时间: 2011-8-5 06:11

这样写效率超级低..还不如不排除 windows..目录..

能否在不降低效率的情况下  dir /s c盘  并跳过 c盘下windows和它的子目录
作者: CrLf    时间: 2011-8-5 11:59

提高效率的办法是将一次 dir 的输出重定向到文件,然后用 for 排除,不过要想完全模拟顶楼代码,估计效率恐怕也不怎么滴,而且代码很长,费力不讨好:
  1. @echo off&setlocal enabledelayedexpansion
  2. set dircmd=C:\
  3. dir /s|findstr /n /v /r /c:"所列文件总数" /c:"Total Files Listed" /c:"^[ 0-9]*Dir" /c:"^[ 0-9]*个目录">tmp.txt
  4. for /f "delims=:" %%a in ('find /c /v ""^<tmp.txt') do set /a all=%%a-1
  5. (for /f "delims==" %%a in ('set') do set %%a=
  6. set all=%all%
  7. set /p a=&set /p b=)<tmp.txt
  8. for /f "tokens=1*" %%a in ('dir') do set end=%%b
  9. for /f %%a in ('copy /z %0 nul') do set hh=%%a^
  10. (for /f "tokens=1* skip=3 delims=:" %%a in (tmp.txt) do (
  11. if %%a lss %all% (
  12. for /f "eol=2 tokens=1,2 delims=\" %%c in ("%%b") do (
  13. if /i "%%c"==" C:" (
  14. if /i "%%c\%%d"==" C:\Windows" (
  15. set echo=
  16. ) else (
  17. set echo=1
  18. echo %a:~2%!hh!%b:~2%!hh!
  19. )
  20. ) else (
  21. set "str=               !n!"
  22. set n=-2
  23. echo !str:~-16! %end%
  24. set str=
  25. )
  26. )
  27. if defined echo echo;%%b
  28. for /f "tokens=2 delims=<>" %%c in ("%%b") do (
  29. if /i %%c==DIR set /a n+=1
  30. )
  31. )
  32. ))>结果.txt
  33. del /f tmp.txt>nul
  34. pause
复制代码
为了省事,此代码不考虑文件名中的特殊字符...
作者: Hello123World    时间: 2011-8-5 17:55

  1. @echo off
  2. (For /f "delims=" %%i in ('dir /s /b c:\ ^| Findstr /v "WINDOWS"') do echo %%i )>1.txt
  3. pause
复制代码
在括号中使用管道符|需要在前面加一个转义字符^。




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