中国DOS联盟论坛

中国DOS联盟

-- 联合DOS 推动DOS 发展DOS --

联盟域名:www.cn-dos.net  论坛域名:www.cn-dos.net/forum
DOS,代表着自由开放与发展,我们努力起来,学习FreeDOS和Linux的自由开放与GNU精神,共同创造和发展美好的自由与GNU GPL世界吧!

游客:  注册 | 登录 | 命令行 | 会员 | 搜索 | 上传 | 帮助 »
中国DOS联盟论坛 » DOS批处理 & 脚本技术(批处理室) » [求助]如何用DOS命令在DIR生成的目录txt文件中提取信息按一定
作者:
标题: [求助]如何用DOS命令在DIR生成的目录txt文件中提取信息按一定 上一主题 | 下一主题
lujisheng
初级用户




积分 117
发帖 5
注册 2004-2-16
状态 离线
『楼 主』:  [求助]如何用DOS命令在DIR生成的目录txt文件中提取信息按一定

有一DIR /S /X /N生成的目录txt 文件,名字为dir.txt
内容为
驱动器 N 中的卷是 MUSIC
卷的序列号是 84D3-ED5D

N:\$OEM$ 的目录

2004-12-26  14:02    <DIR>                       .
2004-12-26  14:02    <DIR>                       ..
2004-12-26  14:03    <DIR>                       $1
2004-12-27  20:35    <DIR>                       $$
2004-12-28  19:18                56              copyth.bat
2004-12-27  20:36    <DIR>          THEMES       Themes
2004-12-27  21:18             3,003              $$RENAME.TXT
2004-12-28  19:33            52,251 LISTTX~1.BAK list.txt.bak
2004-12-28  19:40            47,225              list.txt
2004-12-28  19:52                 0              list1.txt
               5 个文件        102,535 字节

N:\$OEM$\$1 的目录

2004-12-26  14:03    <DIR>                       .
2004-12-26  14:03    <DIR>                       ..
2004-12-21  00:34    <DIR>                       install
2004-12-27  22:49                50              $$RENAME.TXT
               1 个文件             50 字节

N:\$OEM$\$1\install 的目录

2004-12-26  14:04    <DIR>                       .
2004-12-26  14:04    <DIR>                       ..
2004-12-26  11:23            11,776 OFFICE03.MST Office03.MST
2004-12-26  14:13    <DIR>          WINRAR       Winrar
2004-12-26  14:13    <DIR>                       totalcmd
2004-12-26  14:13    <DIR>                       vfloppy
2004-12-26  14:14    <DIR>          UEDIT        UEdit
2004-12-26  17:09    <DIR>                       VCDROM
2004-12-26  17:34             7,680              VISIO03.MST
2004-12-26  17:31             7,680              ONOTE03.MST
2004-12-26  17:33             7,680              PJECT03.MST
2004-12-26  17:29             8,192              FPAGE03.MST
2003-03-11  13:48        24,279,072              dotnetfx.exe
2004-08-20  02:07        10,703,680              dotfix.exe
2004-10-13  04:33        12,672,512              WMP10.exe
2004-12-27  23:06             1,571 INOFFI~2.CMD INOFFICEori.CMD
2004-12-28  18:23               656              INOFFICE.CMD
2004-12-19  23:23           599,001              OS_XP.exe
              11 个文件     48,299,500 字节
。。。。。。。。。


现在想把从它里面提取相关的信息并把这些信息存为固定格式的TXT文件。
格式如下:
[目录名1]
短文件名1="长文件名1"
短文件名2="长文件名2"
......

[目录名2]
短文件名1="长文件名1"
短文件名2="长文件名2"
......

.............

[目录名n]
短文件名1="长文件名1"
短文件名2="长文件名2"

请教大家如何用DOS命令实现。

请DOS大侠出手。

我只知道是用FOR命令来实现,但不知道这个批处理如何完成。

最好能对任何DIR.TXT均有效。

2004-12-28 00:00
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
lujisheng
初级用户




积分 117
发帖 5
注册 2004-2-16
状态 离线
『第 2 楼』:  

附件:一位大侠的文章关于FOR的教程

最强之dos命令 - for
硅谷动力
2004-10-30 8:08:00 文/  


    以前常觉得DOS的命令行功能太弱,无法象UNIX一样可以用命令行完成非常复杂的操作。实际上,当MS从WIN2K开始将命令行增强后,已经借鉴了相当多UNIX的优点,虽然还无法做到象UNIX那么灵活,但已可完成绝大多数的任务,比如用&&和  连接两个(或更多)命令,由前一个的返回值来决定下一个是否执行,等等。而在这些增强中,最明显的,就是FOR命令。

    举个例子,用适当的参数,可用FOR命令将 date /t 的输出 从 "Sat 07/13/2002" 变成你想要的格式,比如, "2002-07-13":


    c:>for /f "tokens=2,3,4 delims=/ " %a in ('date /t') do @echo %c-%a-%b
    2002-07-13


    该例将在(3)中详细说明。

    0. 基本应用

    简单说,FOR是个循环,可以用你指定的循环范围生成一系列命令。最简单的例子,就是人工指定循环范围,然后对每个值执行指定的命令。例如,想快速报告每个硬盘分区的剩余空间:


    for %a in (c: d: e: f do @dir %a   find "bytes free"

    将输出:

    8 Dir(s) 1,361,334,272 bytes free
    15 Dir(s) 8,505,581,568 bytes free
    12 Dir(s) 12,975,149,056 bytes free
    7 Dir(s) 11,658,854,400 bytes free


    用它可以使一些不支持通配符的命令对一系列文件进行操作。在WIN9X中,TYPE命令(显示文件内容)是不支持*.txt这种格式的(WIN2K开始TYPE已支持通配)。遇到类似情况就可以用FOR:


    for %a in (*.txt) do type %a


    这些还不是FOR最强大的功能。我认为它最强大的功能,表现在以下这些高级应用:


    1. 可以用 /r 参数遍历整个目录树

    2. 可以用 /f 参数将文本文件内容作为循环范围

    3. 可以用 /f 参数将某一命令执行结果作为循环范围

    4. 可以用 %~ 操作符将文件名分离成文件名、扩展名、盘符等独立部分


    现分别举例说明如下:

    1. 用 /r 遍历目录树

    当用 *.* 或 *.txt 等文件名通配符作为 for /r 的循环范围时,可以对当前目录下所有文件(包括子目录里面的文件)进行操作。举个例子,你想在当前目录的所有txt文件(包括子目录)内容中查找"bluebear"字样,但由于find本身不能遍历子目录,所以我们用for:


    for /r . %a in (*.txt) do @find "bluebear" %a


    find 前面的 @ 只是让输出结果不包括 find 命令本身。这是DOS很早就有的功能。和FOR无关。

    当用 . 作为循环范围时,for 只将子目录的结构(目录名)作为循环范围,而不包括里面的文件。有点象 TREE 命令,不过侧重点不同。TREE 的重点是用很漂亮易读的格式输出,而FOR的输出适合一些自动任务,例如,我们都知道用CVS管理的项目中,每个子目录下都会有一个CVS目录,有时在软件发行时我们想把这些CVS目录全部去掉:


    for /r . %a in (.) do @if exist %aCVS rd /s /q %aCVS


    先用 if exist 判断一下,是因为 for 只是机械的对每个目录进行列举,如果有些目录下面没有CVS也会被执行到。用 if exist 判断一下比较安全。

    这种删除命令威力太大,请小心使用。最好是在真正执行以上的删除命令前,将 rd /s /q 换成 @echo 先列出要删出的目录,确认无误后再换回rd /s /q:


    for /r . %a in (.) do @if exist %aCVS @echo %aCVS


    可能目录中会多出一层 ".",比如 c:proj elease.CVS ,但不会影响命令的执行效果。

    2. 将某一文件内容或命令执行结果作为循环范围:

    假如你有一个文件 todel.txt,里面是所有要删除的文件列表,现在你想将里面列出的每个文件都删掉。假设这个文件是每个文件名占一行,象这样:


    c: empa1.txt
    c: empa2.txt
    c: empsubdir3.txt
    c: empsubdir4.txt


    那么可以用FOR来完成:


    for /f %a in (todel.txt) do del %a


    这个命令还可以更强大。比如你的 todel.txt 并不是象上面例子那么干净,而是由DIR直接生成,有一些没用的信息,比如这样:


    Volume in drive D is DATA
    Volume Serial Number is C47C-9908

    Directory of D: mp

    09/26/2001 12:50 PM 18,426 alg0925.txt
    12/02/2001 04:29 AM 795 bsample.txt
    04/11/2002 04:18 AM 2,043 invitation.txt
    4 File(s) 25,651 bytes
    0 Dir(s) 4,060,700,672 bytes free


    for 仍然可以解出其中的文件名并进行操作:


    for /f "skip=5 tokens=5" %a in (todel.txt) do @if exist %a DEL %a


    当然,上面这个命令是在进行删除,如果你只是想看看哪些文件将被操作,把DEL换成ech


    for /f "skip=5 tokens=5" %a in (todel.txt) do @if exist %a echo %a


    你将看到:


    alg0925.txt
    bsample.txt
    invitation.txt


    skip=5表示跳过前5行(就是DIR输出的头部信息),tokens=5表示将每行的第5列作为循环值放入%a,正好是文件名。在这里我加了一个文件存在判断,是因为最后一行的"free"刚好也是第5列,目前还想不出好的办法来滤掉最后两行,所以检查一下可保万无一失。

    3. 可以用 /f 参数将某一命令执行结果作为循环范围

    非常有用的功能。比如,我们想知道目前的环境变量有哪些名字(我们只要名字,不要值)。可是SET命令的输出是“名字=值”的格式,现在可以用FOR来只取得名字部分:


    FOR /F "delims==" %i IN ('set') DO @echo %i


    将看到:


    ALLUSERSPROFILE
    APPDATA
    CLASSPATH
    CommonProgramFiles
    COMPUTERNAME
    ComSpec
    dircmd
    HOMEDRIVE
    ......


    这里是将set命令执行的结果拿来作为循环范围。delims==表示用=作为分隔符,由于FOR /F默认是用每行第一个TOKEN,所以可以分离出变量名。如果是想仅列出值:


    FOR /F "delims== tokens=2" %i IN ('set') DO @echo %i


    tokens=2和前例相同,表示将第二列(由=作为分隔符)作为循环值。

    再来个更有用的例子:

    我们知道 date /t (/t表示不要询问用户输入)的输出是象这样的:


    Sat 07/13/2002


    现在我想分离出日期部分,也就是13:


    for /f "tokens=3 delims=/ " %a in ('date /t') do @echo %a


    实际上把 tokens后面换成1,2,3或4,你将分别得到Sat, 07, 13和2002。注意delims=/后面还有个空格,表示/和空格都是分隔符。由于这个空格delims必须是/f选项的最后一项。   

    再灵活一点,象本文开头提到的,将日期用2002-07-13的格式输出:


    for /f "tokens=2,3,4 delims=/ " %a in ('date /t') do @echo %c-%a-%b


    当tokens后跟多个值时,将分别映射到%a, %b, %c等。实际上跟你指定的变量有关,如果你指定的是 %i, 它们就会用%i, %j, %k等。

    灵活应用这一点,几乎没有做不了的事。

    4. 可以用 %~ 操作符将文件名分离成文件名、扩展名、盘符等独立部分

    这个比较简单,就是说将循环变量的值自动分离成只要文件名,只要扩展名,或只要盘符等等。

    例:要将 c:mp3下所有mp3的歌名列出,如果用一般的 dir /b/s 或 for /r ,将会是这样:


    g:mp3Archived-18-01-A游鸿明-下沙游鸿明-01 下沙.mp3
    g:mp3Archived-18-01-A游鸿明-下沙游鸿明-02 21个人.mp3
    ......
    g:mp3Archived-18-01-A王菲-寓言王菲-阿修罗.mp3
    g:mp3Archived-18-01-A王菲-寓言王菲-彼岸花.mp3
    g:mp3Archived-18-01-A王菲-寓言王菲-不爱我的我不爱.mp3
    ......


    如果我只要歌名(不要路径和".mp3"):


    游鸿明-01 下沙
    游鸿明-02 21个人
    ......
    王菲-阿修罗
    王菲-彼岸花
    王菲-不爱我的我不爱
    ......


    那么可以用FOR命令:


    for /r g:mp3 %a in (*.mp3) do @echo %~na


    凡是 %~ 开头的操作符,都是文件名的分离操作。具体请看 for /? 帮助。

    本文举的例子有些可能没有实际用处,或可用其它办法完成。仅用于体现FOR可以不借助其它工具,仅用DOS命令组合,就可完成相当灵活的任务。

2004-12-28 00:00
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
ultralqxq
初级用户




积分 165
发帖 27
注册 2004-11-11
状态 离线
『第 3 楼』:  

for 命令我用得不是很灵活,不过看这题解决办法用DOS命令实现起来会很复杂,你先说一下生成的文件是用来干什么的可以吗?是必须要以你给定的格式也可以吗?

2004-12-29 00:00
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
Climbing
铂金会员

网络独行侠


积分 6962
发帖 2753
注册 2003-4-16
来自 河北保定
状态 离线
『第 4 楼』:  

用任何一条单纯的命令恐怕都很难实现楼主的要求,除非你自己写一个程序,或者sed也可以。



偶只喜欢回答那些标题和描述都很清晰的帖子!
如想解决问题,请认真学习“这个帖子”和“这个帖子”并努力遵守,如果可能,请告诉更多的人!
2004-12-29 00:00
查看资料  发送邮件  访问主页  发短消息 网志  OICQ (653668)  编辑帖子  回复  引用回复
fangxiaoxing
初级用户




积分 120
发帖 9
注册 2004-12-23
状态 离线
『第 5 楼』:  

佩服!学习

2004-12-29 00:00
查看资料  发送邮件  访问主页  发短消息 网志  OICQ (329577271)  编辑帖子  回复  引用回复
lujisheng
初级用户




积分 117
发帖 5
注册 2004-2-16
状态 离线
『第 6 楼』:  

谢谢大家的回复!
To ultralqxq:
这是在做XP自动安装过程中需要的一个文件,名叫$$rename.txt 。它放在$oem$目录下。
安装XP时,我们可以把自己的文件放在$oem$下的规定目录中,比如在$oem$\$$或是$oem$\$1里。
系统在安装过程中会把这些文件复制到相应的目录中去,比如$oem$\$$中的文件会复制到%windir%下,$oem$\$1会复制到%windir%\system32\下。
这些复制是在textmode安装阶段完成的。
于是问题来了,因为这时的系统不支持中文和长文件名,于是你的文件名都就了8.3格式。这是我们不情愿的。
微软提供了一个补救措施,它要求你提供一个名叫$$rename.txt的文件,放在有长文件名的目录中。系统在转到guimode状态时会根据你提供的这个文件来对被改名的文件复位,也就是说这个文件将“教会”系统把8.3格式的文件名改回原状。
微软规定了这个$$rename.txt的格式。我在下面放一个例子。
[Profiles]
ALLUSE~1="All Users"
DEFAUL~1="Default User"
[Profiles\ALLUSE~1]
STARTM~1="Start Menu"
[Profiles\ALLUSE~1\STARTM~1\Programs]
MICROS~1="Microsoft Office"
[Profiles\ALLUSE~1\STARTM~1\Programs\MICROS~1]
GRAPHA~1.LNK="Graph AutoConvert.lnk"
MICROS~1.LNK="Microsoft Excel.lnk"
MICROS~3.LNK="Microsoft Office.lnk"
MI5FC7~1.LNK="Microsoft PowerPoint.lnk"
MICROS~2.LNK="Microsoft Query.lnk"
MI96AF~1.LNK="Microsoft Word.lnk"
[Profiles\ALLUSE~1\STARTM~1\Programs\Startup]
MICROS~1.LNK="Microsoft Office.lnk"
可以看出其结构是:
[目录名1]
短名1="长名1"
短名2="长名2"
.....
短名n="长名n"
[目录名2]
短名1="长名1"
短名2="长名2"
.....
短名n="长名n"
......
......
[目录名n]
短名1="长名1"
短名2="长名2"
.....
短名n="长名n"
正在问题来了,我们怎样才能简便地生成这种格式的文件,总不成要一个个地去写吧。
     

[此贴子已经被作者于2004-12-29 20:52:46编辑过]




2004-12-29 00:00
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
lujisheng
初级用户




积分 117
发帖 5
注册 2004-2-16
状态 离线
『第 7 楼』:  

To Climbing:当然不是说只能用一条命令,用程序和批处理没有什么不可以的。另外,你说的sed是什么啊?

2004-12-29 00:00
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
lujisheng
初级用户




积分 117
发帖 5
注册 2004-2-16
状态 离线
『第 8 楼』:  

To Climbing:看了半天的置顶帖子,明白了两点道理:1.Climbing是这个地方的老大。2.Climbing是一位个性鲜明讲究效率的DOS专家,而且有耐心与爱心。向你致敬。另外明白了sed是怎么回事了,不过太难了。谢谢你对我的问题的关注。

2004-12-29 00:00
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
Climbing
铂金会员

网络独行侠


积分 6962
发帖 2753
注册 2003-4-16
来自 河北保定
状态 离线
『第 9 楼』:  

首先谢谢楼主对我的过誉,我不是什么DOS专家,只是一个喜欢使用命令行的人并且能够用命令行解决一些问题而已。我们还是说说你的问题吧:你的问题在用DOS命令解决起来时有这么几个困难:
1、目录名不方便提取。尤其考虑到某些目录名中带空格等字符时更是如此。
2、并不是所有的文件名都有短文件名,而你的目标文件中只需要将带短文件名的文件列出来。

让DOS命令考虑这么多的异常情况是很困难的,其实现起来的难度已经远远超过了用手工操作的烦琐度,如果楼主一定要按顶楼的要求来实现,恐怕只有通过编程的方式来进行(或者向willsort等高手请教)。我在Windows 2003下试用了一下for命令,或许对你有些帮助:
for /F %I in ('dir /a-d/b/s') do @if not %~nxsI==%~nxI echo %~nxsI=%~nxI这个命令在我的测试过程中发现对长文件名是有效的,但对某些短文件名进行处理里却出了问题,看来是for的变量扩展有问题。



偶只喜欢回答那些标题和描述都很清晰的帖子!
如想解决问题,请认真学习“这个帖子”和“这个帖子”并努力遵守,如果可能,请告诉更多的人!
2004-12-30 00:00
查看资料  发送邮件  访问主页  发短消息 网志  OICQ (653668)  编辑帖子  回复  引用回复
ultralqxq
初级用户




积分 165
发帖 27
注册 2004-11-11
状态 离线
『第 10 楼』:  

如果是想要全自动安装XP,是不需要象你这样子编辑那个文件的。来看看这篇文章就知道了。很简单的。http://www.yesky.com/SoftChannel/72350085605752832/20030918/1729649.shtml不过我觉得用VBS是完全可以处理你上面的情况的。我有时间想想看。

2004-12-31 00:00
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复

请注意:您目前尚未注册或登录,请您注册登录以使用论坛的各项功能,例如发表和回复帖子等。


可打印版本 | 推荐给朋友 | 订阅主题 | 收藏主题



论坛跳转: