批处理命令学习笔记——查找文件

虽然,在WINDOWS系统中,可以直接使用文件查找对话框进行文件查找。然而查找的结果无法与命令行方式交互。我们知道,批处理的优点在于自动性,即一旦启动后,可以无需人工干预,按一系列流程走下去。这与WINDOWS本身的设计思想是不同的。

WINDOWS的核心,就在于它对用户的操作不做任何假定。所以通常Windows程序启动之后,总是在等待用户输入,没有用户输入,WINDOWS程序什么也不做。对于某些应用,WINDOWS应用程序在这方面的优势反而会变成劣势。比如说,配置IP地址,按WINDOWS程序,我们常常需要通过多次点击,键盘输入,才能完成一次配置。而通过配置文件,我们不需要人工干预即可完成此功能。对于后面的应用方式,正是批处理等脚本程序所擅长的事情。

基于上面的认识,我们知道,WINDOWS下面的文件查找应用,有时候是不能满足要求的。那么我们在命令行方式下通过“dir test.file /s”这样的方式查找文件,是否就能充分满足我们的要求呢?答案是否定的。因为 DIR 这个命令,要么只能显示一个目录下面的所有文件列表,要么在一个目录下面搜索一个指定了文件名的文件。我们知道在一个系统中,比如一个编译器,可能在本机存储了两个同名的文件。虽然它们的大小时间都相同,但安装的和不安装的系统环境是不一样的。所以我们可能要寻求一个符合特定目录结构的文件,来确定一个应用程序究竟被安装在了哪里。这一点,正是本例所要介绍的应用。代码如下(假设批处理的文件名为batFind.bat):

@rem =========================================================================
@rem 功能
@rem     在所有的硬盘驱动器上查找目标文件, 并打印出第一个匹配文件所在路径
@rem 语法
@rem     batfind toSearchFile fileTime1 fileTime2 [dirDepth]
@rem 参数
@rem     toSearchFile - 待搜索文件, 可以包含前置子目录
@rem     fileTime1 - 目标文件上次修改的最早时间, 必须是yyyy-mm-dd格式
@rem     fileTime2 - 目标文件上次修改的最晚时间, 必须是yyyy-mm-dd格式
@rem     dirDepth - 搜索的目录深度, 0为根目录, 不指定则所有深度
@rem 附注
@rem     可单独拷贝为一个批处理文件, 参数及用法仍如上所述
@rem 作者
@rem     笑十子@2007-8-23 10:40
@rem -------------------------------------------------------------------------
@echo off

@rem -------------------------------------------------------------------------
@rem 启用延时扩展, 这是搜索处理的需要
@rem -------------------------------------------------------------------------
setlocal ENABLEDELAYEDEXPANSION

@rem -------------------------------------------------------------------------
@rem 初始化搜索变量
@rem -------------------------------------------------------------------------
set torSearchDirs=0
set torRecursiveLevel=0
set savedCurDir=%CD%
set foundDir=

if "%~1" EQU "" (
   echo Please input filename to be searched.
   goto searchAllDriveReturn
)
set torSearchFile=%~1

@rem -------------------------------------------------------------------------
@rem 对搜索的时间范围参数进行检查
@rem -------------------------------------------------------------------------
if "%~2" EQU "" (
   set torFileTime1=1900-01-01
   set torFileTime2=9999-12-31
) else (
   if "%~2" EQU "*" (
       set torFileTime1=1900-01-01
   ) else (
       set torFileTime1=%~2
   )
   if "%~3" EQU "" (
       if "%~2" EQU "*" (
           set torFileTime2=9999-12-31
       ) else (
           set torFileTime2=%~2
       )
   ) else (
       if "%~3" EQU "*" (
           set torFileTime2=9999-12-31
       ) else (
           set torFileTime2=%~3
       )
   )
)
if "%4" EQU "" (set torSearchDepth=9999) else (set /a torSearchDepth=%4)

@rem echo torSearchFile=%torSearchFile%
@rem echo torFileTime1=%torFileTime1%
@rem echo torFileTime2=%torFileTime2%
@rem echo torSearchDepth=%torSearchDepth%

@rem -------------------------------------------------------------------------
@rem 下面的程序段用来搜索本机上有效的硬盘驱动器
@rem -------------------------------------------------------------------------
@set driveList=
regedit /e driveslist.txt HKEY_LOCAL_MACHINE\SYSTEM\MountedDevices
for /f "usebackq skip=2 tokens=3 delims=\:" %%a in (
   `find "DosDevices" driveslist.txt`) do (
   if /I "%%a" GEQ "C" (if exist %%a:\. set driveList=!driveList! %%a:)
)
del driveslist.txt
@rem echo search in driveList: %driveList%

@rem -------------------------------------------------------------------------
@rem 依次在各硬盘上查找目标文件, 如果找到则立即停止
@rem -------------------------------------------------------------------------
for %%a in (%driveList%) do (

    @rem ---------------------------------------------------------------------
    @rem 进入目标驱动器, 并在此根目录下直接进行搜索
    @rem ---------------------------------------------------------------------
    %%a
    cd\
    @rem echo Now search "%torSearchFile%" in drive %%a
    set /a torSearchDirs+=1
    if EXIST "%torSearchFile%" for %%i in ("%torSearchFile%") do (
        if "%%~ti" GEQ "%torFileTime1% 00:00" (
            if "%%~ti" LEQ "%torFileTime2% 23:59" (
                set foundDir=%%a
                goto searchAllDriveReturn
            )
        )
    )

    @rem ---------------------------------------------------------------------
    @rem 如果是最大深度搜索, 则直接使用批处理的for /R 功能
    @rem ---------------------------------------------------------------------
    if %torSearchDepth% EQU 9999 (
        for /r /d %%b in (*) do if EXIST "%%~fb\%torSearchFile%" (
            for %%i in ("%%~fb\%torSearchFile%") do (
                if "%%~ti" GEQ "%torFileTime1% 00:00" (
                    if "%%~ti" LEQ "%torFileTime2% 23:59" (
                        set foundDir=%%~fb
                        goto searchAllDriveReturn
                    )
                )
            )
        )
    @rem ---------------------------------------------------------------------
    @rem 否则调用递归搜索过程
    @rem ---------------------------------------------------------------------
    ) else if %torSearchDepth% GTR 0 (call :recursiveSearch)

    @rem ---------------------------------------------------------------------
    @rem 如果已经找到, 则直接跳出搜索
    @rem ---------------------------------------------------------------------
    if "!foundDir!" NEQ "" goto searchAllDriveReturn
)

:searchAllDriveReturn
    @rem ---------------------------------------------------------------------
    @rem 恢复原来的工作目录, 并打印搜索结果
    @rem ---------------------------------------------------------------------
    %savedCurDir:~0,2%
    cd "%savedCurDir%"
    echo "%foundDir%"
    goto :EOF

@rem =========================================================================
@rem 递归搜索过程
@rem -------------------------------------------------------------------------
:recursiveSearch
    @rem ---------------------------------------------------------------------
    @rem 在每一个子目录下面依次搜索
    @rem ---------------------------------------------------------------------
    set /a torRecursiveLevel+=1
    for /d %%b in (*) do (

        set /a torSearchDirs+=1
        @rem echo curdir="%cd%\%%b"
        if EXIST "%%b\%torSearchFile%" for %%i in ("%%b\%torSearchFile%") do (
            if "%%~ti" GEQ "%torFileTime1% 00:00" (
                if "%%~ti" LEQ "%torFileTime2% 23:59" (
                    set foundDir=%%~fb
                    goto :recursiveSearchReturn
                )
            )
        )

        @rem -----------------------------------------------------------------
        @rem 小于搜索深度, 则进行更深一步的递归搜索
        @rem -----------------------------------------------------------------
        if !torRecursiveLevel! LSS %torSearchDepth% (
            cd "%%b"
            call :recursiveSearch
            cd ..
            if "!foundDir!" NEQ "" goto :recursiveSearchReturn
        )
    )

:recursiveSearchReturn
    set /a torRecursiveLevel-=1
    goto :EOF

本例采用了递归算法进行文件搜索。注意这里的递归算法,从算法上来讲,可能更简单的办法是设定目标文件不存在,然后检查目标文件存在与否,不存在则进入递归,否则退出。这里的算法是是先在本级目录下面检查目标文件是否存在,如不存在,再进入下一目录,进行递归调用。这是由于实测的结果,现有的方法比前一种更快。作者未仔细分析其中的原因,有兴趣的朋友不妨可以探讨一下。  

你可能感兴趣的:(工具/tools)