使用Windows批处理文件备份用户指定位置和用户指定文件扩展名中的文件

时间:2014-07-04 16:23:21

标签: windows batch-file for-loop arguments

我正在创建一个Windows批处理文件,它允许我通过创建扩展名为.bak的文件副本来备份具有特定文件扩展名的特定位置的文件。例如,如果我要为工作批处理文件提供参数“C:\ Test& Folder”(在此示例中,仅包含名为 MyWork.laz 的文件)和“.laz” “,它将切换到正确的驱动器,查看指定的文件夹,在名为 MyWork.laz.bak 的同一文件夹中创建 MyWork.laz 的副本,然后切换回到批处理启动的驱动器。

目前代码如下:

set EXTEN = *%~2%
%~d1
cd "%~f1"
FOR %%I IN %%EXTEN DO COPY %%I %%I.bak
%~d0

但是,当批处理文件到达第4行时,会输出以下错误:

%EXTEN was unexpected at this time.

如何显示Windows如何解释第4行(我使用“.bak”作为我的第二个参数):

FOR %I IN %EXTEN DO COPY %I %I.bak

由于我是Windows批处理编程的新手,而且我对此的研究没有产生任何结果,我会感激任何建议或帮助。

1 个答案:

答案 0 :(得分:1)

简单的批处理解决方案:

@ECHO OFF
FOR /F "usebackq delims=" %%I IN ( `DIR /B "%~1*.%~2"` ) DO COPY "%~1%%I" "%~1%%I.bak" >nul

这个简单的解决方案运行命令 DIR 搜索扩展名作为第一个参数指定的目录中作为第二个参数传递的文件。

命令 DIR 的输出格式使用选项/B设置为简单格式,这意味着只有 DIR 输出没有路径的已找到文件的名称。

FOR 循环中逐行读取此输出,该循环对每个文件执行复制命令以在同一目录中创建备份文件。

但是这个简单的解决方案有一些使用上的缺点:

  1. 不检查是否使用所需的2个参数调用批处理文件。
  2. 没有检查作为第一个参数传递的目录路径是否真的以所需的反斜杠结尾。
  3. 没有检查作为第二个参数传递的扩展名是否按预期包含点。
  4. 因此,更好的解决方案是批处理文件:

    @ECHO ON
    SET "Folder=%~1"
    SET "Extension=%~2"
    IF "%Folder%"=="" GOTO Usage
    IF "%Extension%"=="" GOTO Usage
    IF "%Folder:~-1%"=="\" SET "Folder=%Folder:~0,-1%"
    IF "%Extension:~0,1%"=="." SET "Extension=%Extension:~1%"
    FOR /F "usebackq delims=" %%I IN ( `dir /b "%Folder%\*.%Extension%"` ) DO COPY "%Folder%\%%I" "%Folder%\%%I.bak" >NUL
    GOTO EndBatch
    
    :Usage
    CLS
    ECHO Usage: %~n0 ["][Drive:]Path["] Extension
    ECHO.
    ECHO Examples:
    ECHO.
    ECHO    %~n0 "C:\My Files\" txt
    ECHO.
    ECHO    %~n0 C:\Temp\ doc
    ECHO.
    PAUSE
    
    :EndBatch
    SET Folder=
    SET Extension=
    

    第二行将第一个参数分配给环境变量文件夹,并删除周围的双引号(如果存在的话)。如果目录路径包含&%等特殊字符,则命令 SET 的整个参数必须为双引号。

    第三行将第二个参数分配给环境变量扩展,并删除周围的双引号(如果存在的话)(不太可能但不是不可能)。

    第四行和第五行检查是否使用至少2个参数调用批处理文件。

    只有在删除双引号后才能安全地完成对第一个参数缺失的检查,否则如果目录路径包含&等特殊字符,则会出现语法错误消息,导致批处理文件的执行中断。 / p>

    IF ""C:\Test & Folder""==""
    

    会导致语法错误

    IF "C:\Test & Folder"==""
    

    由命令行解释器解析正确。

    第六行检查目录路径的最后一个字符是否为反斜杠。如果是这种情况,则删除末尾的反斜杠。如果在结尾处丢失则附加反斜杠也可能相反。但是在下面的 FOR 循环中使用3次反斜杠可以使这行更容易阅读。

    如果在使用点调用批处理文件时指定了文件扩展名,则第七行会从文件扩展名的开头删除一个点。

    其他方面应该是自我解释的。


    除了Expack3在第一条评论中回答问题:

    每当启动新进程时,Windows都会为环境变量及其值分配内存,并将环境数据从父进程复制到被调用进程的环境内存。因此,每个进程都有自己的环境缓冲区,可以修改,添加或删除环境变量,而不会影响其他正在运行的进程,包括父进程。

    在运行批处理文件时调用进程cmd.exe,该文件解释并执行批处理文件中的命令。默认情况下,cmd.exe在到达的批处理文件末尾终止。在终止cmd.exe时,环境变量缓冲区也被释放,因此批处理文件添加,修改或删除哪些变量并不重要。因此,通常不必删除批处理文件中临时使用的环境变量。

    但是,不是双击批处理文件,或通过快捷方式(* .lnk文件)或Windows任务计划程序运行批处理文件,而是可以直接从命令提示符窗口中运行批处理文件这意味着来自已经运行的cmd.exe进程。

    在这种情况下,处理批处理文件完成后,执行的批处理文件添加的环境变量将保留在环境缓冲区中。如果接下来从同一个命令提示符窗口中执行下一个批处理文件,这可能会导致问题,这个批处理文件偶然也会使用第一个批处理文件的一个环境变量,但在第一次使用之前没有初始化环境变量。第二批文件中缺少变量初始化的错误与第一批文件中不删除变量相结合的错误现在导致第二批文件的执行与第二批文件分别在命令提示符中分别运行第二批文件相比不同窗口。

    删除临时使用的环境变量的另一个原因是环境变量的内存有限。在启动进程之前,Windows为环境变量分配的内存在进程执行期间不会增长。因此,如果从其他批处理文件调用一个批处理文件,并且没有批处理文件删除临时使用的环境变量,则可能会发生突然没有新变量的可用内存或执行期间现有变量的更大字符串批处理层次结构。大型公司中的登录批处理文件通常是批处理文件的集合,如果每个批处理文件本身直接或通过其他批处理文件间接调用,则需要从环境缓冲区中获取越来越多的内存,而不会删除临时使用的环境变量。

    因此,在退出批处理文件之前删除临时使用的环境变量更安全,但对于大多数批处理文件而言,这是不必要的,只需将总批处理时间增加几微秒。

    使用类似的行:

    set "Folder=%~f1"
    

    对于此批处理文件是不够的。它从传递的目录路径中删除双引号,并且如果可以找到目录,还会将相对目录路径更改为绝对目录路径。

    但如果此路径已经是绝对路径,则不会从目录路径末尾删除反斜杠。

    对于此批处理文件,目录路径不一定是绝对路径,因为命令 DIR COPY 也可以使用相对路径。

    将相对目录路径扩展到绝对目录路径只需要几毫秒的批处理执行而没有任何好处,除了通过插入带有 ECHO 打印名称的行来扩展批处理文件复制文件的完整路径,在 FOR 循环中进行目视检查。