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\ 检查当前运行的批处理文件的位置;如果相等,则批处理文件立即终止。
最后,原始批处理文件(由%~f02访问)被复制(未移动)到新位置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 抑制)和触发exit /B 命令的错误(由于@987654352 @) 离开批处理文件,因此不会尝试执行最后一行。
您也可以使用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 这个带括号的整个块是
echo 被视为单个命令行。
)
echo 这条续行 & ^
echo 也是。
2) 请注意,此类参数引用会在读取和解析命令行或块后立即解析,因此在实际执行之前。