无忧启动论坛

 找回密码
 注册
搜索
系统gho:最纯净好用系统下载站投放广告、加入VIP会员,请联系 微信:wuyouceo
查看: 47465|回复: 37
打印 上一主题 下一主题

DOS有奖问答No6:关于循环命令FOR的使用

[复制链接]
跳转到指定楼层
1#
发表于 2006-1-10 12:46:23 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
[这个贴子最后由gmy在 2006/04/13 11:15am 第 2 次编辑]

为使大家深入讨论DOS技术,本版主会经常提出一些有难度的问题,回答正确的给予加威望等形式的奖励,并且原贴加精,以便查阅。
DOS有奖问答No6:关于循环命令FOR的使用

请用FOR命令简化以下批处理,要求用FOR命令,在纯DOS环境。

if exist c:\boot.ini goto c
if exist d:\boot.ini goto d
if exist e:\boot.ini goto e
...
if exist w:\boot.ini goto w

:c
set drv=c:
copy %drv%\boot.ini %drv%\boot.bak
goto end
:d
set drv=d:
copy %drv%\boot.ini %drv%\boot.bak
goto end
:e
set drv=e:
copy %drv%\boot.ini %drv%\boot.bak
goto end
...  
:w
set drv=w:
copy %drv%\boot.ini %drv%\boot.bak
goto end
:end

编程意图:依次查找C到W盘根目录下的BOOT.INI,将首次找到的BOOT.INI复制到同一目录下,重命名为BOOT.BAK,找到后不再查找,结束程序。


[color=#B22222]重要提示:本贴派生出来的其它问题如ATTRIB,No Ready。。请参看 一键GHOST 的相关批处理,已经得到了完美解决!
2#
发表于 2006-1-10 22:19:29 | 只看该作者

DOS有奖问答No6:关于循环命令FOR的使用

[这个贴子最后由magictek在 2006/01/14 09:50pm 第 1 次编辑]

如果不使用批处理,一句话来完成:
For %f In (c d e f g h i j k l m n o p q r s t u v w)Do If Exist %f:\Boot.Ini Copy %f:\Boot.Ini %f:\Boot.Bak
缺点是不能找到以后不再查找,只能从C一直查到W
如果可以用批处理,就比较容易实现一些:
@Echo Off
For %%f in (c d e f g h i j k l m n o p q r s t u v w) Do If Exist %%f:\Boot.Ini Set Drv=%%f
Copy %Drv%:\Boot.Ini %Drv%:\Boot.Bak
不过我在测试的时候发现还是有点点问题,比如说我D盘F盘各有一个Boot.Ini,的确是检测到F盘有以后就备份F盘的了,但是F盘的Boot.Ini这是Copy了,源文件还在,每次都只能检测到F盘就不能到D盘了,如果要在DOS工具中间加入这个语句,我相反觉得第一种方式(即每个盘都找,只要有就都备份)相对还要安全一些
还是和以前一样,我对葛老师的问答积极参与,但是加密帖子,避免妨碍别人思路和积极性,如果我的回答有什么错误,请葛老师斧正
回复

使用道具 举报

3#
发表于 2006-1-11 00:34:35 | 只看该作者

DOS有奖问答No6:关于循环命令FOR的使用

[这个贴子最后由magictek在 2006/01/14 09:50pm 第 3 次编辑]

自己发现犯了个错误,第二种里面其实我是对%f反复多次赋值,有效的只是最后赋值的那个,第二条不算,重新想过

越想越复杂,本来正在尝试用for %%f in (c d e f) do set drv%%f=%%f:来对每个分区都赋值一个变量再来搜索的,忽然发现其实只要将c至w的次序反过来,便能够找到第一个有Boot.Ini的分区并对%f最终赋值,然后对该变量代表的分区中的文件备份就可以了
@Echo Off
For %%f in (w v u t s r q p o n m l k j i h g f e d c) Do If Exist %%f:\Boot.Ini Set Drv=%%f
Copy %Drv%:\Boot.Ini %Drv%:\Boot.Bak

个人感觉这个题目非常不错的,使用到了DOS里面最为复杂的for以及比较复杂的if,总记得以前哪位前辈说过:如果完全熟悉for的用法,DOS就可以称为精通了,在一些比较经典的题目里面,例如删除QQ目录中的号码文件夹,for还是很好用的,但是至于for的高级应用,别人写的我看得懂,但是要自己写一个很不错得还是觉得缺乏灵感,光就这一点以后还需要向葛老师多多请教
回复

使用道具 举报

4#
 楼主| 发表于 2006-1-11 13:57:08 | 只看该作者

DOS有奖问答No6:关于循环命令FOR的使用

公布正确答案 (不是100%符合题意,仅供参考)
@echo off
set drv=notfound
for %%i in (c d e f g h i j k l m n o p q r s t u v w) do if exist %%
i:\boot.ini set drv=%%i
if %drv%==notfound goto err
:ok
cls
echo OK! %drv%\boot.ini is found !
goto end
:err
cls
echo Sorry! boot.ini is not found!
goto end
:end
echo
echo
pause
REM 看点:
REM 1.参数传递:i%%传给%%drv,以解决跳出FOR以后i%%失效的问题。
REM 2.DRV的初始值:DRV的值不能为空,否则if %drv%=="" goto err语句运行失败
回复

使用道具 举报

5#
发表于 2006-1-11 22:20:10 | 只看该作者

DOS有奖问答No6:关于循环命令FOR的使用

drv值不能为空,这一点的确需要注意
回复

使用道具 举报

6#
发表于 2006-1-13 16:59:33 | 只看该作者

DOS有奖问答No6:关于循环命令FOR的使用

[这个贴子最后由xusen在 2006/01/13 05:00pm 第 1 次编辑]

REM 2.DRV的初始值:DRV的值不能为空,否则if %drv%=="" goto err语句运行失败
空了应该也是可以的
@echo off
for %%a in (c d e f g h i j k l m n o p q r s t u v w) do if exist %%a:\boot.ini set drv=%%a
if %drv%#==# goto end
echo %drv%

:end
回复

使用道具 举报

7#
发表于 2006-1-13 17:03:41 | 只看该作者

DOS有奖问答No6:关于循环命令FOR的使用

[这个贴子最后由xusen在 2006/01/13 05:17pm 第 1 次编辑]

建议颠倒盘符顺序  因如果有两个区有BOOT.INI则会选择后个
@echo off
for %%a in (w v u t s r q u o n m l k j i h g f e d c) do if exist %%a:\boot.ini set drv=%%a
if %drv%#==# goto 结束
:处理
copy %drv%:\boot.ini %drv%:\boot.bak /y >nul

:结束
回复

使用道具 举报

8#
 楼主| 发表于 2006-1-16 08:05:50 | 只看该作者

DOS有奖问答No6:关于循环命令FOR的使用

xusen 指出的两点很重要,也很正确,加威望!
回复

使用道具 举报

9#
发表于 2006-3-3 10:20:58 | 只看该作者

DOS有奖问答No6:关于循环命令FOR的使用

真的不知道大家有没有实际试过,根本不得行
boot.ini是系统文件,隐藏文件,用COPY是拷贝不了的!!!!!!

其实这个批处理只需要下面这一句就足够了:
@for %%X in (e f g h i j k l m n o p q r s t u v w) do @if exist %%X:\boot.ini attrib %%X:\boot.ini -h -s&&copy %%X:\boot.ini %%X:\boot.bak&&attrib %%X:\boot.ini +h +s&&exit /b

当然,这是一个复合语句,愿意的话也可以将它扩展成下面这个样子:
@echo off
for %%X in (c d e f g h i j k l m n o p q r s t u v w) do @(
if exist %%X:\boot.ini (
attrib %%X:\boot.ini -h -s
copy %%X:\boot.ini %%X:\boot.bak
attrib %%X:\boot.ini +h +s
exit /b
)
if %%X==w echo Not found!
)

关键是要修改boot.ini的属性,当然还要改回来。
另外,大家都知道命令之间可以用&&连接,(或||,有点小区别)
还有就是 可以用括号来实现复合语句,和C语言中的大括号{}差不多
最后,批处理有循环但没有跳出循环的类似break continue的语句,
只能用exit /b了。也可以用goto:eof.或者自己在文件最后定义一个
标号end.
回复

使用道具 举报

10#
发表于 2006-3-3 15:25:49 | 只看该作者

DOS有奖问答No6:关于循环命令FOR的使用

[这个贴子最后由xusen在 2006/03/03 03:33pm 第 2 次编辑]

if 语句后面的"(" 及 &&连接 只能在WINDOWS环境下的批处理脚本上使用,纯DOS环境可能用不了。
回复

使用道具 举报

11#
发表于 2006-3-3 18:53:50 | 只看该作者

DOS有奖问答No6:关于循环命令FOR的使用

哈哈原来是纯DOS,眼花了,我说嘛,我这个偶而用一下批处理的都觉得简单的问题怎么会有人不会呢

最好是指定一下是DOS4.0还是6.0还是98版还是6.2还是DOS7.1 还是其他什么
DOS,不同版本的区别还是不少

但boot.ini一般为隐藏系统文件,用copy是拷贝不了的,这一点我还是比较肯定的
回复

使用道具 举报

12#
发表于 2006-3-3 18:57:18 | 只看该作者

DOS有奖问答No6:关于循环命令FOR的使用

if %drv%#==# goto end
这种方法我倒是经常使用,版主居然也不大知道,看来我还是对批处理略有理解嘛
自我奖励一下啦,呵呵
回复

使用道具 举报

13#
发表于 2006-3-3 19:03:06 | 只看该作者

DOS有奖问答No6:关于循环命令FOR的使用

下面引用由我是神仙2006/03/03 06:53pm 发表的内容:
哈哈原来是纯DOS,眼花了,我说嘛,我这个偶而用一下批处理的都觉得简单的问题怎么会有人不会呢
最好是指定一下是DOS4.0还是6.0还是98版还是6.2还是DOS7.1 还是其他什么
DOS,不同版本的区别还是不少
但boot.ini一般 ...
对标准的文本文件,不管它的属性如何,可以用 Type 命令复制,如要复制隐藏系统文件C:\BOOT.INI 为 C:\BOOT.BAK 可以这样:
[color=#8B0000]
TYPE C:\BOOT.INI>C:\BOOT.BAK
回复

使用道具 举报

14#
发表于 2006-3-4 00:49:49 | 只看该作者

DOS有奖问答No6:关于循环命令FOR的使用

没必要在一个Attrib上面争论这么长时间吧,这个题目的重点是For的使用上面,不是在Attrib上面,在实际应用中,即使忘记使用Attrib了,也是很容易Debug出来的
回复

使用道具 举报

15#
发表于 2006-3-5 20:09:05 | 只看该作者

DOS有奖问答No6:关于循环命令FOR的使用

呵呵原来没看见这个问题,现在既然看到了还是发表一点个人看法吧

找到后不再查找,结束程序。
GMY的明显不符要求嘛,怎么叫正确答案呢,
建议改成“参考答案”(他看到了xusen的修改,为什么不改呢?)

纯DOS的批处理功能太弱,是戴着锁链跳舞,编一些小程序真的是不简单啊
不过平时用的多的还是在windows中用一些简单的批处理。windows中的DOS一直
在不断的进步,现在应该说功能非常强大了

用type来拷贝隐藏的文本文件,不错

xusen的不错,指出变量drv可以为空,但他好像没像GMY那样给drv赋初值,这是
不大对的。事实上,变量drv一定要有初值,虽然初值可以为空
谁知道drv这个变量在你用之前是否为空呢?编程,即使是批处理,不能太想当然了吧
我一般是用set drv= 来给drv赋一个空的初值
(其实可以用set local,但纯DOS又好像不行)

其实GMY把这个问题要求用FOR来做真的是不大好做,选的方向不对嘛
用纯DOS的FOR不能中断循环,就是说即使C盘中才有boot.ini,它也
要傻傻的执行二十几遍,晕
我觉得这种循环根本不应该用FOR ,应该用if goto等用法来构造循环,
找到了就跳出来,多爽
参考一下:
test.bat
@echo off
if  %1F==F goto usage
:test
if  %1F==F goto notfound
if exist %1:\boot.ini goto found
shift
goto test
:found
type %1:\boot.ini>%1:\boot.bak 2>nul
goto end
:usage
echo  Usage:
echo  test c d e f  (input all disks you want to test)
goto end
:notfound
echo Not found!
goto end
:end
回复

使用道具 举报

16#
发表于 2006-3-5 20:11:31 | 只看该作者

DOS有奖问答No6:关于循环命令FOR的使用

当然,只要不要求用FOR,是个人都知道可以这样写,哈哈
回复

使用道具 举报

17#
发表于 2006-3-5 21:09:38 | 只看该作者

DOS有奖问答No6:关于循环命令FOR的使用

刚才看了sidac在另一贴中的提示,可以通过不用call的调用来退出循环,
确实可行。这样此程序也就可以用FOR来写,倒是简洁一些了:
@echo off
echo copy %%1:\boot.ini %%1:\boot.bak>found.bat
for %%a in (c d e f g h i j k l m n o p q r s t u v w) do if exist %%a:\boot.ini found.bat %%a
echo Not found!
回复

使用道具 举报

18#
发表于 2006-3-5 21:12:01 | 只看该作者

DOS有奖问答No6:关于循环命令FOR的使用

本来也是想用type来拷贝的,不过对于纯DOS中怎么显示特殊字符不是很清楚
我只知道windows中可用 echo ^> 来显示一个大于号,在纯DOS中不知该怎么写
回复

使用道具 举报

19#
发表于 2006-3-5 22:41:36 | 只看该作者

DOS有奖问答No6:关于循环命令FOR的使用

@echo off
echo exit|command /k prompt type %%1:\boot.ini$g%%1:\boot.bak$_|find ">">found.bat
for %%a in (c d e f g h i j k l m n o p q r s t u v w) do if exist %%a:\boot.ini found.bat %%a
echo Not found!
回复

使用道具 举报

20#
发表于 2006-3-6 12:57:12 | 只看该作者

DOS有奖问答No6:关于循环命令FOR的使用

用 IF 也可以这样试试:
====================
@echo off
if not %1#==# goto 下一步
set drv=c d e f g h i j k l m n o p q r s t u v w
call %0 %drv%
:下一步
shift
if %0#==# goto 结束
if not exist %0:\boot.ini goto 下一步
type %0:\boot.ini >%0:\boot.bak
:结束
set drv=
回复

使用道具 举报

21#
发表于 2006-3-6 13:23:53 | 只看该作者

DOS有奖问答No6:关于循环命令FOR的使用


纯DOS调用自身以前没用过,昨天浏览DOS联盟时倒是发现了那儿的版主willsort早就提过这种用法,没来得及改 :)
现在的DOS倒是支持直接调用标号了.
回复

使用道具 举报

22#
发表于 2006-3-19 17:09:43 | 只看该作者

DOS有奖问答No6:关于循环命令FOR的使用

寫批處理文件是我的職業, 暈吧!
@ECHO OFF
:INIT
SET FILE=%0
IF @%FILE%==@ SET FILE=\AUTOEXEC.BAT
IF NOT @%1==@ GOTO %1
CALL %FILE% MAIN
GOTO END
:MAIN
FOR %%I IN (C D E F G H I J K L M N O P Q R S T U V W X Y Z) DO IF EXIST %%I:\BOOT.INI CALL %FILE% BACK %%I
GOTO END
:BACK
SET DRV=%2:
ATTRIB -R -S -H %DRV%\BOOT.INI
COPY %DRV%\BOOT.INI %DRV%\BOOT.BAK
GOTO END
:END
回复

使用道具 举报

23#
发表于 2006-4-1 22:31:04 | 只看该作者

DOS有奖问答No6:关于循环命令FOR的使用

大家写了不少批处理,都没有发现每个批处理都有一个致命的缺陷:
大家都从c-z检测是否存在boot.ini,难道你们不了解,如果一个磁盘如果有问题(例如光驱没盘)而访问时会出现错误提供的情况吗?(Not Ready)。
如何处理呢?
回复

使用道具 举报

24#
发表于 2006-4-13 09:44:27 | 只看该作者

DOS有奖问答No6:关于循环命令FOR的使用

我试了一下,在windows中只要dir一下就可以了.
检测一下errorlevel即可
在DOS中,如果不加载光驱,那就不存在问题,
如果加载了光驱,光驱的盘符是很好确认的,跳过即可
回复

使用道具 举报

25#
发表于 2006-4-13 19:33:45 | 只看该作者

DOS有奖问答No6:关于循环命令FOR的使用

我怎么觉得好像编程程序运行啊
回复

使用道具 举报

26#
发表于 2006-6-2 23:13:47 | 只看该作者
顶起来,不错的帖子,论坛改版后就沉下去了
回复

使用道具 举报

27#
发表于 2006-6-25 16:32:42 | 只看该作者
原帖由 magictek 于 2006-6-2 11:13 PM 发表
顶起来,不错的帖子,论坛改版后就沉下去了


顶一下
回复

使用道具 举报

28#
发表于 2006-6-25 23:10:28 | 只看该作者
看晕了,多学习~~~
回复

使用道具 举报

29#
发表于 2006-8-19 19:42:42 | 只看该作者
对孜孜不倦的精神致敬!好帖!顶起来!
回复

使用道具 举报

30#
发表于 2006-8-20 20:35:03 | 只看该作者
看不太懂,只懂一些.
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|Archiver|捐助支持|无忧启动 ( 闽ICP备05002490号-1 )

闽公网安备 35020302032614号

GMT+8, 2024-11-17 04:24

Powered by Discuz! X3.3

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表