Windows命令提示符cmd
不会将批处理文件缓存在内存中,而是逐行从文件中读取1。因此,一旦move
命令完成,就会立即收到错误提示,因为文件再也找不到了。
您可以像这样调用批处理文件来抑制错误:
"C:\temp\move_me.bat" 2> nul
但这会不经意地抑制每个其他错误消息。
无论如何,也许以下方法适合您——这是脚本C:\temp\move_me.bat
:
if /I "%~dp0"=="D:\temp\" exit /B
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.
不再出现。
上述的
if
查询立即退出复制的批处理文件的执行,因此其其他代码不会运行两次。
如果您不想跳过复制的批处理文件的执行,请删除
if
命令行并修改
copy
命令行如下:
copy "%~f0" "D:\temp\%~nx0" > nul || exit /B
"D:\temp\%~nx0" & del "%~f0"
> nul
部分可以抑制显示消息(包括摘要
1 file(s) copied.
)。使用
||
操作符仅在复制失败时才执行下一条命令。因此,当执行原始批处理文件时,复制完成如预期。当复制后的批处理文件运行时,
copy
尝试将批处理文件复制到自身,导致消息
The file cannot be copied onto itself.
(由
> nul
抑制)和错误触发
exit /B
命令(由于
||
),以退出批处理文件,因此不会尝试执行最后一行。
您也可以使用move
实现相同的功能;相关代码如下:
if /I "%~dp0"=="D:\temp\" exit /B
move "%~f0" "D:\temp\%~nx0" & "D:\temp\%~nx0"
或者,如果您希望移动的脚本不跳过其他代码:
if /I not "%~dp0"=="D:\temp\" move "%~f0" "D:\temp\%~nx0" & "D:\temp\%~nx0"
if
查询是必要的,因为与copy
不同,如果源和目标相等,move
不会返回错误。
这里提供了一个全面的解决方案,用于批处理文件将自己移动并在移动后将控制权交给已移动的文件。查看所有的说明备注,以找出哪个批处理文件实例运行了哪些代码:
@echo off
set "_TARGET=D:%~pnx0" & rem /* (this defines the movement destination;
echo Batch file: "%~f0"
echo [executed by both files before the movement check]
if /I "%~f0"=="%_TARGET%" (
echo Batch file: "%~f0"
echo [executed only by the moved file]
) else (
echo Batch file: "%~f0"
echo [executed only by the original file]
> nul move "%~f0" "%_TARGET%"
"%_TARGET%"
echo Batch file: "%~f0"
echo [executed only by the original file, but after the moved one has finished]
)
echo Batch file: "%~f0"
echo [executed only by the moved file after the movement check]
exit /B
1) 注意,带括号的代码块(
/)
和继续的行^
被视为单个命令行:
(
echo 整个带括号的块都是
echo 视为单个命令行。
)
echo 这个继续的行 & ^
echo 也是。
2) 注意,这样的参数引用在命令行或块被读取和解析之后立即解析,因此在实际执行之前就已经解析了。
move
命令之后的行将不再被识别,我想。也许你可以将move
改为copy
并在:continuation
部分使用del
命令删除原始批处理文件... - aschipflmove
,但是通过&
连接下一行,那么它就会被识别... - aschipfl