
[英]Moving a batch file into directories added while the batch file is running
[英]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
查询是必要的,因为move
与copy
相反,如果源和目标相等则不会返回错误。
这是一个批处理文件的综合解决方案,它可以自动移动并在之后控制移动的文件。 查看所有解释性说明,找出哪个批处理文件实例运行的代码:
@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.