自动批处理文件

时间:2017-03-17 15:15:51

标签: windows batch-file

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

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

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

我收到错误

  

找不到批处理文件。

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

2 个答案:

答案 0 :(得分:3)

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,但这不是我们想要的。 & operator允许下一个命令在前一个命令完成时执行。虽然未使用call,但仍然执行下一个命令,因为整个行已被cmd读取和解析。但是执行控制现在位于批处理文件的新实例中,因此不再显示错误消息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 portion会禁止显示消息(包括摘要1 file(s) copied.)。 || operator仅在复制失败时执行下一个命令。因此,当执行原始批处理文件时,将按预期完成复制。当复制的批处理文件运行时,copy会尝试将批处理文件复制到自身上,这会导致消息The file cannot be copied onto itself.(由> nul抑制)并且会在错误中触发{{1}命令(由于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查询是必要的,与move相反,如果源和目标相等,则不会返回错误。

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

copy

1)请注意,带括号的代码块@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 / (和续行)被视为一个命令行:

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

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

答案 1 :(得分:0)

批处理文件是逐行执行的,而不是一次性读入内存。在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

或者批处理文件复制到目的地,然后继续删除原始副本。

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