海鸥航迹

学习之笔记,好文之收集。

导航

精彩批处理代码

接收键盘输入字符串的程序

:: Get user input - includes error check
@echo off
echo e102'set %%1='> %temp%.\t1.dat
for %%? in (w q) do echo %%?>> %temp%.\t1.dat
:input
echo.
echo Type input:
FC con nul /lb1 /n |FIND "1:" > %temp%.\t2.bat
:: Error checking begins here
FIND "|" %temp%.\t2.bat > nul
if not errorlevel=1 goto error
FIND "=" %temp%.\t2.bat > nul
if not errorlevel=1 goto error
FIND " nul
if not errorlevel=1 goto error
FIND ">" %temp%.\t2.bat > nul
if not errorlevel=1 goto error
:: Error checking end
DEBUG %temp%.\t2.bat  nul
call %temp%.\t2.bat 字符串
for %%? in (t1.dat t2.bat) do del %temp%.\%%?
echo 字符串=%字符串%
goto eof
:error
echo.
echo @PROMPT Invalid input. Invalid characters: $Q $L $G $B$_> %temp%.\t2.bat
%comspec% /c %temp%.\t2.bat |FIND ":"
goto input
:eof

一个修改文件的更新日期的程序

@echo off
rem 保存系统时间
echo.|date>sysdate.bat
echo.|time>systime.bat
rem 修改系统时间为指定时间,日期为参数一,时间为参数二,文件名为参数三
date %1
time %2
rem 修改文件的时间
copy %3+,,>nul
rem 恢复系统时间
echo date %%4>current.bat
call sysdate
echo time %%3>current.bat
call systime
rem 程序执行完毕
echo Success.
del systime.bat
del sysdate.bat
del current.bat
echo on 

PING某个区段内的所有IP的程序

  在命令行输入 a.bat 0 1 2 3 4 5 6 7 8 9 ,就能显示某区段的所有 IP 地址 192.168.1.0 - 192.168.1.99 ,将其中的 echo 改成 ping 就行,其中的 choice 和 if 语句是等待用户判断是否继续,可以删除,但这样中断程序比较麻烦。
CODE:  [Copy to clipboard]
--------------------------------------------------------------------------------

@echo off
:redo
if "%1" == "" goto end
for %%a in (0,1,2,3,4,5,6,7,8,9) do echo 192.168.1.%1%%a
choice continue
if errorlevel 2 goto end
shift
goto redo
:end

一个定时器程序

程序中的 CURRENT.BAT 可以更换为自己需要执行的内容。FIND 一句的时间可以根据自己的需要设定,也可用参数%1代替。还可以改为 TIME 改为 DATE 以完成的定期执行的功能。

------------------------------

  Quote:
::CURRENT.BAT
@echo off
echo Haha, it's the time to go!!

::TIMER.BAT
@echo off
:start
echo.|time|find "10:30:00">run.bat
choice /c:y /t:y,59 /n>nul
call run.bat
goto start 

ASCII汇编代码,延迟精度为0.001秒,适用平台为MS-DOS/Win9x/WinNT。

  德国人Herbert Kleebauer给出了一个通用方案,通过ASCII汇编器间接产生一个sleep.exe程序来实现延迟,这个程序分为DOS和Win两个模块,分别调用DOS系统中断服务和WindowsAPI。
CODE:  [Copy to clipboard]
--------------------------------------------------------------------------------

:: Sleep.bat - Sleep/Delay/Wait n seconds
:: Herbert Kleebauer(Germany) - 2005/05/29
:: Modified by Will Sort - 2005/06/02, 07-25
@echo off
echo q | debug>nul
echo Bj@jzh`0X-`/PPPPPPa(DE(DM(DO(Dh(Ls(Lu(LX(LeZRR]EEEUYRX2Dx=>sleep.com
echo 0DxFP,0Xx.t0P,=XtGsB4o@$?PIyU WwX0GwUY Wv;ovBX2Gv0ExGIuht6>>sleep.com
echo T}{z~~@GwkBG@OEKcUt`~}@MqqBsy?seHB~_Phxr?@zAB`LrPEyoDt@Cj?>>sleep.com
echo pky_jN@QEKpEt@ij?jySjN@REKpEt@jj?jyGjN@SEKkjtlGuNw?p@pjirz>>sleep.com
echo LFvAURQ?OYLTQ@@?~QCoOL~RDU@?aU?@{QOq?@}IKuNWpe~FpeQFwH?Vkk>>sleep.com
echo _GSqoCvH{OjeOSeIQRmA@KnEFB?p??mcjNne~B?M??QhetLBgBPHexh@e=>>sleep.com
echo EsOgwTLbLK?sFU`?LDOD@@K@xO?SUudA?_FKJ@N?KD@?UA??O}HCQOQ??R>>sleep.com
echo _OQOL?CLA?CEU?_FU?UAQ?UBD?LOC?ORO?UOL?UOD?OOI?UgL?LOR@YUO?>>sleep.com
echo dsmSQswDOR[BQAQ?LUA?_L_oUNUScLOOuLOODUO?UOE@OwH?UOQ?DJTSDM>>sleep.com
echo QTqrK@kcmSULkPcLOOuLOOFUO?hwDTqOsTdbnTQrrDsdFTlnBTm`lThKcT>>sleep.com
echo @dmTkRQSoddTT~?K?OCOQp?o??Gds?wOw?PGAtaCHQvNntQv_w?A?it\EH>>sleep.com
echo {zpQpKGk?Jbs?FqokOH{T?jPvP@IQBDFAN?OHROL?Kj??pd~aN?OHROd?G>>sleep.com
echo Q??PGT~B??OC~?ipO?T?~U?p~cUo0x>>sleep.com
sleep.com>sleep.exe
echo wait %1 seconds:
sleep.exe %1000
del sleep.com
del sleep.exe

时钟(Clock)

1、暂停(Pause)、延迟(Delay)、等待(Wait)、睡眠(Sleep)

1)for+set+if,时间精度为0.01秒,适用平台为WinNT/2K/XP/2003。

  利用for解析变量%time%并存为两个时间点%start%和%now%,再利用set /a计算两个时间点的时间差,最后用if判断时间差是否达到设定的暂停时间。
CODE:  [Copy to clipboard]
--------------------------------------------------------------------------------

  @echo off
  setlocal enableextensions
  echo %time%
  call :ProcDelay 200
  echo %time%
  goto :EOF

  :ProcDelay delayMSec_
  setlocal enableextensions
  for /f "tokens=1-4 delims=:. " %%h in ("%time%") do set start_=%%h%%i%%j%%k
    :_procwaitloop
    for /f "tokens=1-4 delims=:. " %%h in ("%time%") do set now_=%%h%%i%%j%%k
    set /a diff_=%now_%-%start_%
  if %diff_% LSS %1 goto _procwaitloop
  endlocal & goto :EOF

如何删除所有的空目录?

用这个批处理就可以了。
dir /ad/b/s c:\ |sort /r >c:\kill.txt
For /f "tokens=*" %%i in (c:\kill.txt) DO rd "%%i"
del c:\kill.txt

我想用ECHO向另一P批处理文件写入“%~dp0”字符,可是被翻译成路径写入了,而不是该字符本身,不知各位高手是否有办法??
eg:
echo “%~dp0”>test.bat

试试:
echo "%%~dp0">test.bat
文件名中的扩展名的判定
7.如何在批处理中判断文件后缀?实现诸如以下的效果。

if "%1" == "*.dll" goto dll
if "%1""=="*.inf" goto inf

1、如果文件名所指的文件是单个文件,且存在这个文件,且其中不包含路径的指定,那么可以使用以下的方案
CODE:  [Copy to clipboard]
--------------------------------------------------------------------------------

for %%x in (*.dll) do if exist "%1" goto dll
for %%x in (*.inf) do if exist "%1" goto inf

2、如果文件名所指的文件是单个文件,但是它不存在,且其中不包含路径的指定,那么可以使用以下的方案
CODE:  [Copy to clipboard]
--------------------------------------------------------------------------------

if not exist %temp%\_getext_\nul md %temp%\_getext_
echo _getext_> %temp%\_getext_\%1
if exist %temp%\_getext_\*.dll goto dll
if exist %temp%\_getext_\*.inf goto inf

3、如果程序应用环境是NT系列的命令行,且文件名中只有一个分隔主文件名和扩展名的句点,可以使用以下的方案
CODE:  [Copy to clipboard]
--------------------------------------------------------------------------------

for /f "delims=. tokens=2" %%x in ("%1") do set _ext=%%x
if "%_ext%"=="dll" goto dll
if "%_ext%"=="inf" goto dll

目录的存在判定

这似乎是个很简单的问题,在我见过的和我编过的绝大部分批处理中,目录判定都使用的是这个经典格式:

      if exist directory\nul command argument(s)

      可以说,这个技巧的创始者确实对DOS的研究十分深刻,至少他发现了 nul 所代表的设备管理机制与文件管理机制之间复杂而微妙的关系,nul设备与. 和 .. 等一样可以在大部分路径下直接引用而不会产生系统错误。

      但是,也正像 .. 不能在根目录下引用(这在NT CMD中被修改了)一样,nul也有它的局限性。

      当我们在 MSDOS7.10 的环境中加载了 DOSLFN 以实现长文件名支持时, DOSLFN 的某些 BUG 会将 \NUL 的引用转义,此时会将文件判定为目录。

  Quote:
C:\>echo.>test.txt

C:\>if exist test.txt\nul echo Exist dir "test.txt"
Exist dir "test.txt"

C:\>

如果说这仅仅是doslfn的问题,那么我们可以禁止DOSLFN,然后再将测试阵地转到光盘上。由于光盘具有独特的文件系统CDFS,\NUL的引用失效了,目录仍然无法被识别出来,不过总算不会把文件误判作目录了。

  Quote:
E:\>dir /ad /b
BOOT
DOS71

E:\>if exist boot\nul echo Exist dir "BOOT"

E:\>

我们再转到时新的CMD@WinXP中,如果目录名中包含空格,则无法用长文件名识别其存在。

  Quote:
C:\>md "my test"

C:\>if not exist "my test"\nul echo Not exist "my test"
Not exist "my test"

C:\>if not exist "my test\nul" echo Not exist "my test"
Not exist "my test"

C:\>
关于目录的存在判定

用 if exist directory\nul command argument(s)
的方法只要目录含有空格无论如何是匹配不正确的。
我实际应用中一般用下面的方法:
CODE:  [Copy to clipboard]
--------------------------------------------------------------------------------

md "my test"
cd "my test" &&echo Exist directory "test"
这样会很准确,但也是有缺点的,那就是会进入其目录

引用环境变量中路径时的防御字符的选择

  Quote:
  另一个与此相关的问题是,路径变量后的防御字符。

  当我们使用环境变量引用一个路径时,一般是直接引用,比如:

  %temp%\_temp.bat

  但这样存在一个问题:如果%temp%是某个驱动器的根目录,比如C:\,那么以上的引用就变成了:
  C:\_temp.bat

  路径中出现了双斜线,这在MS-DOS和Win9x中将会引起语法错误,所以有人采用了在变量后加一个句点的做法,即:

  %temp%.\_temp.bat

  这样的话,如果%temp%为根目录,引用结果就是:C:\.\_temp.bat,如果不是根目录(比如C:\temp),就是C:\temp.\_temp.bat。

  这利用了句点在不同用法中所呈现出的二义性:在前一用法中,它表示当前目录,而根目录下的当前目录自然仍然是根目录;而在后一用法中,它表示目录名中主名与扩展名的分隔符,因为句点后没有实际的扩展名,所以C:\temp.仍然表示的是C:\temp目录。

  但是,这带来了一个新问题:如果路径中出现了相对路径的特殊引用符,该怎么办?比如,如果%temp%是表示当前目录的 . 或者上一级目录的 ..,那么 %temp%.\_temp.bat 的引用就变成了:

  ..\_temp.bat 或者 ...\_temp.bat

  这显然又不是我们所需要的结果,那么我们该怎么办呢?

  答案在你们的手里 :-)

posted on 2010-09-12 10:02  海天一鸥  阅读(500)  评论(0编辑  收藏  举报