Windows shell 编程 ¬¬——将指定文件夹中的所有文件名输出到一个文件中

    技术2022-05-11  17

    问题分析:该任务主要有三个问题要解决1)如何存放指定的文件夹,2)如何遍历文件夹下的所有文件;3)如何将遍历的文件输出到文件中。下面就逐一来解决这些问题。 问题解决: 1. 如何存放指定的文件夹 在Shell中主要通过set 来存放环境变量。比如:Set var=xxxx。如果要删除该变量,则使用Set var=。在shell脚本中并没有类似数组这样的变量来帮助你存放数据。所以只能考虑将几个文件名放到一个string中,然后通过字符串识别来分别读出这些变量。示例如下: SET DirList=C:/A C:/B C:/D FOR /D %%i IN (%DirList%) DO ECHO %%i     (如直接在命令行输入,%%i应写为%i) 利用FOR语句就可以分别读出C:/A,C:/B和C:/D。此处也算是对FOR /D命令的一种灵活运用了。当然除此之外,也可以将变量存放于某文件,然后再循环读出,此处就不再详细说明了。 上面的语句还有些不完善的地方,那就是不支持文件名中出现空格的情况。比如C:/D E, 这种情况,命令只能识别出空格前的部分,造成文件名错误。避免这种情况的方法就是用引号把文件名包起来,如下所示: SET DirList=”C:/A” “C:/B” “C:/D E”   2. 如何遍历文件夹中的所有文件呢? 解决了多个文件夹名存放的问题,现在需要遍历文件夹了。幸运的是shell为我们提供了一个命令可以方便的遍历完文件夹中的文件。命令如下: FOR /R [[drive:]path] %variable IN (set) DO command [command-parameters] 于是很自然的想到了如下的语句: SET  DirList = ”C: A” “C: B” “C: D E”         FOR   / D %%m IN  ( %DirList% )   DO   (             FOR   / R %%m %%i IN  ( * )   DO   ECHO  %%i         ) 但不幸的是,这个脚本运行时出错。主要问题就是在第二个FOR语句中并不支持%%m, 在path位置上出现%%m让FOR有点不知所措。于是我们想到是否可以先把%%m赋值给一个变量,然后再将变量用于FOR语句。修改后结果如下: SET  DirList = ”C: A” “C: B” “C: D E”      FOR   / D %%m IN  ( %DirList% )   DO   (         SET   DIR = %%m         FOR   / R % DIR % %%i IN  ( * )   DO   ECHO  %%i      ) 很不幸,程序是可以运行,但结果为空。因为对于一个完整的复合语句,比如此处的循环嵌套,其中用到的变量已经在运行前全部替换成当前的环境变量的值,运行时环境变量的改变并不会影响程序中正在使用的那个值。由于在FOR运行前DIR还为定义,第二个FOR循环中自然找不到要遍历的目录了,所以就什么结果都不会有了。 J 这下可该如何是好呢?感觉有点走头无路了。只好再看看帮助了,发现shell提供了setlocal enabledelayedexpansion语句可以让程序打开延迟扩展特性,使用临时变量。就如同下面这个计算文件数目的程序: @echo off rem 打开延迟扩展特性 setlocal enabledelayedexpansion set /a n=0 for /f %%i in ('dir /b') do (      set /a n=!n!+1      ) echo 当前目录下的文件和目录总数为:%n% endlocal pause 似乎看到救星了,于是改变了一下原来的代码得到: SETLOCAL  enabledelayedexpansion         SET  DirList = ”C: A” “C: B” “C: D E”         FOR   / D %%m IN  ( %DirList% )   DO   (              SET   DIR = %%m              FOR   / R ! DIR ! %%i IN  ( * )   DO   ECHO  %%i         )        ENDLOCAL 结果出来了,但是不全,只能出来第一个目录的所有文件。似乎!DIR!的改变还是不能影响第二个FOR的执行。再一次对shell表示失望! 最后的努力,来自于cell神奇的力量,求助函数。 @ECHO   off SET  DirList = ”C: A” “C: B” “C: D E” FOR   / d %%m IN  ( %DirList% )   DO   ( CALL   :GenerateList  %%m ) GOTO   :EOF   :GenerateList FOR   / R %* %%i IN  ( * )   DO   (       ECHO  %%i ) GOTO   :EOF J 终于还是笑到了最后! 另外还有一个命令可以遍历所有的文件:DIR /A:-D /B /S 因此得到解法二: @ECHO   off SET  DirList = ”C: A” “C: B” “C: D E” FOR   / d %%m IN  ( %DirList% )   DO   ( CALL   :GenerateList  %%m ) GOTO   :EOF :GenerateList DIR  %*  / A:-D  / / S GOTO   :EOF   3. 将结果输出了文件 在shell中一般采用重定向将结果输出到文件。可以考虑两种方式: append(>>), new(>); 考虑到使用append还需要在使用前清空文件,比较麻烦。因此还是使用后者。最终的结果如下: @ECHO   off CALL  : Transverse >. Data cachePackagesFile GOTO   :EOF   :Transverse SET  DirList = ”C: A” “C: B” “C: D E” FOR   / d %%m IN  ( %DirList% )   DO   ( CALL   :GenerateList  %%m ) GOTO   :EOF   :GenerateList FOR   / R %* %%i IN  ( * )   DO   (       ECHO  %%i ) GOTO   :EOF   总结:看似简单一个任务,结果却耗费了颇多的精力才得以最终解决。虽然传说中的shell是超简单的脚本编程,但却是是用法颇多诡异之处,特别是相对于高级的编程语言。不过鉴于shell和windows命令的紧密邦定,能够熟练掌握shell编程应该还是有不少好处吧。   参考: 1.Windows.Shell.Script.Programming.for.the.Absolute.Beginner 2.跟我学CMD实战系列: http://lifesinger.org/blog/?p=11  3.中国DOS联盟  http://www.cn-dos.net/forum/   

    最新回复(0)