Board logo

标题: [文件操作] [已解决]批处理管道命令和SORT命令使用出错,怎么办? [打印本页]

作者: mac007cn    时间: 2011-1-11 20:39     标题: [已解决]批处理管道命令和SORT命令使用出错,怎么办?

在“E:\学生作业”文件夹下有70个文件夹,分别是USER01、USER02、……、USER70,每个文件夹下又有若干文件名以“13”打头的.TXT文件,都是学生提交的作业。我写了一个批处理程序,如下,其功能是显示所有“13”开头的学生作业文件,并统计总作业份数。
  1. @echo off
  2. setlocal EnableDelayedExpansion
  3. setlocal EnableExtensions
  4. set "ClassNO=13"
  5. set "WorkDir=E:\学生作业"
  6. set /a n=0
  7. for /R "%WorkDir%" %%a in (%ClassNO%*.txt) do (
  8.     echo %%a
  9.     set /a n+=1
  10. )
  11. echo 如上所示,共找到%n%份%ClassNO%班的作业!
复制代码
运行结果:
E:\学生作业\USER33\1330温丽方.txt
E:\学生作业\USER39\1310白霜霜.txt
E:\学生作业\USER31\1317葛莹莹.txt
E:\学生作业\USER28\1342张胜男.txt
E:\学生作业\USER28\1343张胜.txt
E:\学生作业\USER64\13   康士娇TXT.txt
E:\学生作业\USER32\1360任丽冉.txt
如上所示,共找到7份13班的作业!


现在我想把For /R循环输出的文件列表进行排序,方便查找个别学生提交作业情况,在For /R外侧加了圆括号和sort命令,
  1. @echo off
  2. setlocal EnableDelayedExpansion
  3. setlocal EnableExtensions
  4. set "ClassNO=13"
  5. set "WorkDir=E:\学生作业"
  6. set /a n=0
  7. (
  8. for /R "%WorkDir%" %%a in (%ClassNO%*.txt) do (
  9.     echo %%a
  10.     set /a n+=1
  11. )
  12. )|sort
  13. echo 如上所示,共找到%n%份%ClassNO%班的作业!
复制代码
但是结果最后输出令我大为意外:
1
2
3
4
5
6
7
E:\学生作业\USER28\1342张胜男.txt
E:\学生作业\USER28\1343张胜.txt
E:\学生作业\USER31\1317葛莹莹.txt
E:\学生作业\USER32\1360任丽冉.txt
E:\学生作业\USER33\1330温丽方.txt
E:\学生作业\USER39\1310白霜霜.txt
E:\学生作业\USER64\13   康士娇TXT.txt
E:\学生作业>(echo E:\学生作业\USER28\1342张胜男.txt   & set /a n+=1  )
E:\学生作业>(echo E:\学生作业\USER28\1343张胜.txt   & set /a n+=1  )
E:\学生作业>(echo E:\学生作业\USER31\1317葛莹莹.txt   & set /a n+=1  )
E:\学生作业>(echo E:\学生作业\USER32\1360任丽冉.txt   & set /a n+=1  )
E:\学生作业>(echo E:\学生作业\USER33\1330温丽方.txt   & set /a n+=1  )
E:\学生作业>(echo E:\学生作业\USER39\1310白霜霜.txt   & set /a n+=1  )
E:\学生作业>(echo E:\学生作业\USER64\13   康士娇TXT.txt   & set /a n+=1  )
如上所示,共找到0份13班的作业!


为什么结果前半部分出现了1234567后边又出现了带有echo和set命令的输出呢?而最后却说有“0份13班的作业”呢?当我把“| sort”命令删除后运行批处理显示正常。百思不得其解。

谢谢。

[ 本帖最后由 mac007cn 于 2011-1-13 10:32 编辑 ]
作者: hanyeguxing    时间: 2011-1-11 21:15

楼主要做的查找、排列规则是什么?
  1. @echo off&setlocal ENABLEDELAYEDEXPANSION
  2. set "ClassNO=a"
  3. set "WorkDir=E:\学生作业"
  4. for /f "delims=" %%a in ('dir /s/a/b "%WorkDir%\%ClassNO%*.txt"^|sort') do (
  5. echo %%a
  6. set/a n+=1
  7. )
  8. echo 如上所示,共找到%n%份%ClassNO%班的作业!
  9. pause
复制代码

作者: mac007cn    时间: 2011-1-11 21:41     标题: 回复 2楼 的帖子

“E:\学生作业\USER28\1342张胜男.txt”
每个学生作业文件名都是“两位数班号+两位数学+姓名”的形式,我本意是对文件名中“班号学号”排序来着,想用“For的输出|SORT /+15”来实现,结果却令我很郁闷,为什么没用SORT命令时正常、加上SORT后就多出1234567这些劳什子东西呢?我是想弄明白为什么这样会出如此离奇的错误。

当然,你给的代码很棒。谢谢。

[ 本帖最后由 mac007cn 于 2011-1-11 21:44 编辑 ]
作者: zqz0012005    时间: 2011-1-11 22:03

以前在verybat讨论过,管道前后的命令加括号的问题,归根到底就是管道的运行机制和多次启动子cmd带来的相关问题。

楼主的问题可以多加几个@
  1. @echo off
  2. setlocal EnableDelayedExpansion
  3. setlocal EnableExtensions
  4. set "ClassNO=13"
  5. set "WorkDir=E:\学生作业"
  6. set /a n=0
  7. (
  8. for /R "%WorkDir%" %%a in (%ClassNO%*.txt) do @(
  9.     echo %%a
  10.     set /a n+=1 >nul
  11. )
  12. )|@sort
  13. echo 如上所示,共找到%n%份%ClassNO%班的作业!
  14. pause
复制代码

作者: zqz0012005    时间: 2011-1-11 22:04

几乎都忘了这个问题了。verybat实在可惜。。。
  1. @echo off
  2. setlocal EnableDelayedExpansion
  3. set n=123
  4. echo !n!|more
  5. (echo !n!)|more
  6. reg.exe add "HKEY_CURRENT_USER\Software\Microsoft\Command Processor" /v DelayedExpansion /t REG_DWORD /d 1 /f >nul
  7. (echo !n!)|more
  8. reg.exe delete "HKEY_CURRENT_USER\Software\Microsoft\Command Processor" /v DelayedExpansion /f >nul
  9. (echo !n!)|more
  10. pause
复制代码

作者: hanyeguxing    时间: 2011-1-11 22:09     标题: 回复 3楼 的帖子

原帖由 mac007cn 于 2011-1-11 21:41 发表
“E:\学生作业\USER28\1342张胜男.txt”
每个学生作业文件名都是“两位数班号+两位数学+姓名”的形式,我本意是对文件名中“班号学号”排序来着,想用“For的输出|SORT /+15”来实现,结果却令我很郁闷,为什么没用SORT命令时正常、加上SORT后就多出1234567这些劳什子东西呢?我是想弄明白为什么这样会出如此离奇的错误。

当然,你给的代码很棒。谢谢。
意思是不管上级目录名,只对文件名排列?如果是这样,那么显示的要是文件名,还是带完整路径?所有子目录中是否有重名文件?
如果文件不是很多,可以这样:
  1. @echo off
  2. set "ClassNO=13"
  3. set "WorkDir=E:\学生作业"
  4. for /R "%WorkDir%" %%a in (%ClassNO%*.txt) do set "#%%~na#%%a=="
  5. for /f "tokens=2 delims==#" %%a in ('set #') do (
  6.     echo %%a
  7.     set/a n+=1
  8. )
  9. echo 如上所示,共找到%n%份%ClassNO%班的作业!
  10. pause
复制代码

[ 本帖最后由 hanyeguxing 于 2011-1-11 22:41 编辑 ]
作者: mac007cn    时间: 2011-1-12 08:54     标题: 回复 4楼 的帖子

原帖由 zqz0012005 于 2011-1-11 22:03 发表
以前在verybat讨论过,管道前后的命令加括号的问题,归根到底就是管道的运行机制和多次启动子cmd带来的相关问题。

楼主的问题可以多加几个@@echo off
setlocal EnableDelayedExpansion
setlocal EnableExtensio ...

这个代码已经很接近我的目标了。原来圆括号前面也是能加@的啊。
但为什么最后的%n%显示依然是0呢?

[ 本帖最后由 mac007cn 于 2011-1-12 09:08 编辑 ]
作者: mac007cn    时间: 2011-1-12 09:04     标题: 回复 5楼 的帖子

这段代码是不是说明在批处理文件里用setlocal开启DelayedExpansion与注册表里对CMD开启DelayedExpansion是不一样的,为什么呢?谢谢。
PS:veryBAT倒闭了么?

[ 本帖最后由 mac007cn 于 2011-1-12 09:09 编辑 ]
作者: mac007cn    时间: 2011-1-12 10:14     标题: 但是这样可以:

  1. @echo off
  2. for /l %%a in (0 1 9) do set "#%%a=%%a"
  3. (
  4. echo %#2%
  5. echo %#9%
  6. echo %#6%
  7. echo %#3%
  8. echo %#1%
  9. echo %#4%
  10. echo %#8%
  11. echo %#5%
  12. echo %#7%
  13. echo %#0%
  14. )|sort
复制代码
输出是正确的:
  1. 0
  2. 1
  3. 2
  4. 3
  5. 4
  6. 5
  7. 6
  8. 7
  9. 8
  10. 9
复制代码
但是只要管道|之前括号内有循环FOR 就不行。郁闷。
作者: Batcher    时间: 2011-1-12 10:20     标题: 回复 9楼 的帖子

4楼不是告诉你解决方法了吗,为何还在郁闷?
作者: mac007cn    时间: 2011-1-12 16:57     标题: 回复 10楼 的帖子

请看7楼。。。
请高手给介绍一下5楼的注册表项的含义吧
我改了注册表,可是最后%n%或!n!依然为0,为什么啊?
谢谢。
作者: zqz0012005    时间: 2011-1-12 22:25

因为管道两边的命令是在子CMD中运行的,子进程不会改变父进程的变量空间。
要改变n最好用2楼的方法。
作者: powerbat    时间: 2011-1-12 23:45     标题: 回复 9楼 的帖子

从版主的解释得到提示:
因为%#2%这些变量是在父进程里定义的,子进程可以继承。
作者: mac007cn    时间: 2011-1-13 10:25     标题: 回复 12楼 的帖子

原帖由 zqz0012005 于 2011-1-12 22:25 发表
因为管道两边的命令是在子CMD中运行的,子进程不会改变父进程的变量空间。
要改变n最好用2楼的方法。

子CMD进程……,原来如此,终于明白了。多谢多谢!
原来,之前俺对5楼的“管道前后的命令加括号的问题,归根到底就是管道的运行机制和多次启动子cmd带来的相关问题”不太理解。

[ 本帖最后由 mac007cn 于 2011-1-13 10:28 编辑 ]
作者: mac007cn    时间: 2011-1-13 10:30     标题: 回复 13楼 的帖子

原帖由 powerbat 于 2011-1-12 23:45 发表
从版主的解释得到提示:
因为%#2%这些变量是在父进程里定义的,子进程可以继承。

“在父进程里定义的,子进程可以继承”——精辟!
作者: yhcbird    时间: 2011-1-18 09:18

请问下:setlocal EnableExtensions  这个是什么???
和setlocal EnableDelayedExpansion 区别是什么??




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