繁体   English   中英

自动批处理文件

[英]Self-moving batch file

我正在寻找批处理文件在执行后将自身移动到已知位置的方法。 自我移动 - 似乎是最恰当的名字,但我确信它有一个技术术语。 我希望所有其他代码运行移动批处理文件。

move "C:\temp\move_me.bat"  "D:\temp\move_me.bat"  

其中move_me.bat是放在c:\\ temp中的同名批处理文件,移动到d:\\ temp。

我收到了错误

找不到批处理文件。

即使批处理文件移动位置。 所以我有点困惑。 我是否需要压制错误,或者最好是复制批处理文件并删除源代码? 或者有更好的方法吗?

Windows命令提示符cmd不会在内存中缓存不批处理文件,它从第1行文件中的行读取它们。 因此, move命令完成后会立即收到错误,因为无法再找到该文件。

您可以像这样调用批处理文件来抑制错误:

"C:\temp\move_me.bat" 2> nul

但这也无意中抑制了所有其他错误消息。

无论如何,也许以下方法适合您 - 这是脚本C:\\temp\\move_me.bat

if /I "%~dp0"=="D:\temp\" exit /B
rem // (some other code here...)
copy "%~f0" "D:\temp\%~nx0"
"D:\temp\%~nx0" & del "%~f0"

首先,针对D:\\temp\\ ;检查当前运行的批处理文件的位置。 如果相等,批处理文件立即终止。

最后,将原始批处理文件(由%~f0 2访问)复制(不移动)到新位置D:\\temp (文件名, %~nx0 ,保持不变)。

下一行从新位置运行批处理文件,但不使用call ,这是返回调用批处理脚本所需的,但这不是我们想要的。 &运算符允许下一个命令在前一个命令完成时执行。 虽然未使用call ,但仍然执行下一个命令,因为整行已被cmd读取和解析。 但是执行控制现在位于批处理文件的新实例中,因此The batch file cannot be found.错误消息The batch file cannot be found. 不再出现。

上述if查询立即退出批处理文件的副本,因此其他代码不会运行两次。

如果您不想跳过复制的批处理文件的执行,请删除if命令行并修改copy命令行以获取此信息:

rem // (some other code here...)
copy "%~f0" "D:\temp\%~nx0" > nul || exit /B
"D:\temp\%~nx0" & del "%~f0"

> nul部分禁止显示消息(包括1 file(s) copied.的摘要1 file(s) copied. )。 || 只有在复制失败的情况下, operator才会执行下一个命令。 因此,当执行原始批处理文件时,将按预期完成复制。 复制的批处理文件运行时, copy尝试将批处理文件复制到自身,这将导致消息The file cannot be copied onto itself. (由> nul抑制)并且在一个错误中触发exit /B命令(由于|| )离开批处理文件,因此不会尝试执行最后一行。


使用move也可以实现相同的行为; 所以相关代码如下所示:

if /I "%~dp0"=="D:\temp\" exit /B
rem // (some other code here...)
move "%~f0" "D:\temp\%~nx0" & "D:\temp\%~nx0"

或者,如果您希望不为移动的脚本跳过其他代码:

rem // (some other code here...)
if /I not "%~dp0"=="D:\temp\" move "%~f0" "D:\temp\%~nx0" & "D:\temp\%~nx0"

if查询是必要的,因为movecopy相反,如果源和目标相等则不会返回错误。


这是一个批处理文件的综合解决方案,它可以自动移动并在之后控制移动的文件。 查看所有解释性说明,找出哪个批处理文件实例运行的代码:

@echo off

rem // Define constants here:
set "_TARGET=D:%~pnx0" & rem /* (this defines the movement destination;
                         rem     in your situation, the original batch file is
                         rem     `C:\temp\move_me.bat`, so the target file is
                         rem     `D:\temp\move_me.bat` (only drive changes)) */

rem // (code that runs for both batch file instances...)
echo Batch file: "%~f0"
echo   [executed by both files before the movement check]

rem // Check whether current batch file is the moved one:
if /I "%~f0"=="%_TARGET%" (

    rem // (code that runs for the moved batch file instance only...)
    echo Batch file: "%~f0"
    echo   [executed only by the moved file]

) else (

    rem // (code than runs for the original batch file instance only...)
    echo Batch file: "%~f0"
    echo   [executed only by the original file]

    rem // Actually move the batch file here, then give control to the moved one:
    > nul move "%~f0" "%_TARGET%"
    "%_TARGET%"

    rem /* (code that runs for the original batch file instance only;
    rem     this is run after the moved batch file has finished;
    rem     you must not use `goto` herein as the target label cannot be found,
    rem     because the original file does no longer exist at this point!) */
    echo Batch file: "%~f0"
    echo   [executed only by the original file, but after the moved one has finished]

)

rem // (code that runs for the moved batch file instance only...)
echo Batch file: "%~f0"
echo   [executed only by the moved file after the movement check]

exit /B

1)请注意,带括号的代码块( / )和续行^被视为单个命令行:

(
    echo This entire parenthesised block is
    echo considered as a single command line.
)
echo This continued line & ^
echo as well.

2)注意,一旦读取和解析了命令行或块,就会立即解析这些参数引用,因此在实际执行之前。

批处理文件是逐行执行的,而不是一次性读入内存。 move命令后还有其他命令吗?

但是,批处理文件还具有调用另一个批处理文件将覆盖批处理文件的功能。

所以,你可能会逃脱:

if "%1" == "continuation" goto :continuation

REM interesting things go here

move "C:\Temp\move_me.bat" "D:\Temp\move_me.bat"
"D:\Temp\move_me.bat" continuation

:continuation
REM more interesting things go here

或者, 批处理文件复制到目标并继续删除原始副本。

或者让您的批处理文件将其自身复制到目标(并自行删除)作为它的第一件事。 这可能更容易理解。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM