|
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 |
|
|
fangxiaoxing
初级用户
积分 120
发帖 9
注册 2004-12-23
状态 离线
|
|
2004-12-29 00:00 |
|
|
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 |
|
|
ultralqxq
初级用户
积分 165
发帖 27
注册 2004-11-11
状态 离线
|
『第
10 楼』:
如果是想要全自动安装XP,是不需要象你这样子编辑那个文件的。来看看这篇文章就知道了。很简单的。http://www.yesky.com/SoftChannel/72350085605752832/20030918/1729649.shtml不过我觉得用VBS是完全可以处理你上面的情况的。我有时间想想看。
|
|
2004-12-31 00:00 |
|