例如,我想运行一个 Windows 批处理文件,比如 upgrade.bat,它将一堆文件从源目录复制到批处理文件所在的目录。问题是,复制的文件之一可能是更新版本的升级.bat,以便批处理文件在其仍在运行时会覆盖自身。
这似乎会导致批处理文件执行的一些不可预测的行为,因此我想避免复制仍在运行的批处理文件。理想情况下,我希望现有版本的 upgrade.bat 一直运行到完成,然后下次运行新版本。有没有(简单的)方法可以实现这一目标?
例如,我想运行一个 Windows 批处理文件,比如 upgrade.bat,它将一堆文件从源目录复制到批处理文件所在的目录。问题是,复制的文件之一可能是更新版本的升级.bat,以便批处理文件在其仍在运行时会覆盖自身。
这似乎会导致批处理文件执行的一些不可预测的行为,因此我想避免复制仍在运行的批处理文件。理想情况下,我希望现有版本的 upgrade.bat 一直运行到完成,然后下次运行新版本。有没有(简单的)方法可以实现这一目标?
@ECHO OFF
SETLOCAL
IF /i NOT "%~dp0"=="%temp%\" (
COPY /y "%~dpnx0" "%temp%\%~nx0" >nul
"%temp%\%~nx0"
)
ECHO Now we run the rest of the original UPGRADE.BAT
开头的这一系列行upgrade.bat
应该可以工作。
看看我们是否从%temp%
. 如果没有,则将此文件复制到 temp 并从那里运行它。
因此,批处理实际上是从中运行的,%temp%
并且可能会覆盖原始版本。
为此,必须满足以下要求:
copy
必须是exit /B
or exit
。那是:
@echo off
rem Do program business here...
echo Anything
rem Parse/load following commands before execute they:
(
rem Copy many files, probably a newer version of myself
xcopy /Y *.*
rem You may execute other commands here...
echo Files copied!
rem Terminate *this version* of the running Batch file
exit /B
)
您可以使用 start 命令将副本作为最后一个操作运行,以从另一个终端启动它。检查这个例子,特别是最后几行。
@echo off
set CUR_FILE=batman.bat
set FOUND_EQUAL="FALSE"
set FROM_DIR=c:\temp\galeria\
SETLOCAL DisableDelayedExpansion
FOR /R %FROM_DIR% %%F IN (*) DO (
SET "p=%%F"
SETLOCAL EnableDelayedExpansion
SET ABC=!p:%FROM_DIR%=!
IF NOT !ABC! == !CUR_FILE! (
echo copying %%F
copy "%%F" .
)
ENDLOCAL
)
echo trying to copy file with the same name [last operation]
start copy "%FROM_DIR%%CUR_FILE%" .
@echo off
cmd /c copy "C:\somepath\upgrade.bat" "%0" & %0
这将启动一个新的 cmd 进程并将当前批处理文件替换为“C:\somepath\upgrade.bat”并重新启动批处理文件
是否可以选择使用版本后缀标记批处理文件的每个新版本并使用第二个批处理文件作为启动器?
比如你的payload批处理文件是upgrade.bat,后续版本会被命名为upgrade_001.bat, upgrade_002.bat, upgrade_003.bat .. or upgrade_201305122134(后缀是yyyymmddHHMM),新的批处理文件launcher.bat会查找最新的批量升级文件,查找后缀最高的文件并执行
if NOT "%1"=="RUN" (
copy "%~0" temp_update.cmd
temp_update.cmd RUN
)
只需将其放在您的 cmd 文件的顶部,任何名称都可以用于临时文件。
使批处理文件将自身复制到updateNow.bat
然后运行updateNow.bat
:所以内容update.bat
是:
if %0 == update (
copy update.bat updateNow.bat
updateNow.bat
) else (
copy newUpdate.bat update.bat
)