我正在 Windows (Server 2019) 下运行以下批处理脚本来移动(和重命名)大量 tiff 文件(大约数百万个):
@echo off
set "mainFolder=."
setlocal enabledelayedexpansion
for /D %%i in ("%mainFolder%\*") do (
set "DateFolder=%%~nxi"
set "init=1"
for %%f in ("%%i\*.tif") do (
if !init!==1 (
echo Processing folder: !DateFolder!
set "init=0"
)
set "TiffFullPath=%%~dpf"
set "TiffPExt=%%~nxf"
set "Tiff=!TiffPExt:~0,-4!"
if not exist %mainFolder%\..\clus\!Tiff! mkdir %mainFolder%\..\clus\!Tiff! >nul
move /y %%f %mainFolder%\..\clus\!Tiff!\!Tiff!_!DateFolder:~7,8!.tif >nul
)
)
echo Done
当我监控任务管理器时,我发现 RAM 内存消耗在大约 30 分钟内不断从零增加到最大值 (32 GB),最终我收到“没有足够的内存资源来处理此命令”。
这可能是什么原因,因为我知道移动文件只涉及更改操作系统中的指针/引用,因此内存根本不应该增加。
我建议首先阅读这个答案,了解有关命令SETLOCAL和ENDLOCAL的详细信息。假设在两个 FOR 循环内某处使用了命令 SETLOCAL,而没有匹配的 ENDLOCAL,这将解释内存使用量的永久增加,直到在批处理文件处理期间发生可用堆栈内存错误条件结束。但发布的代码仅在批处理文件顶部包含一次 SETLOCAL 。发布的代码不应增加内存使用量。发布的代码很可能不完整,并且遗漏了导致内存使用量不断增加的部分。
发布的代码无法处理全名(驱动器+路径+名称+扩展名)包含一个或多个感叹号的文件。下面是批处理文件的一个变体,它不使用延迟变量扩展来处理任何独立于文件扩展名
.tif
或 .tiff
的 TIFF 文件名,这两个文件扩展名都是使用通配符模式 *.tif
作为.tiff
文件的短 8.3 文件扩展名是 .TIF
.
@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "MainFolder=."
for %%I in ("%MainFolder%\..\clus") do set "DestFolder=%%~fI"
(for /D %%I in ("%MainFolder%\*") do if exist "%%I\*.tif" set "DateFolder=%%~nxI" & call :MoveFiles "%%~fI") & echo Done& exit /B
:MoveFiles
echo Processing folder: "%DateFolder%"
for %%J in ("%~1\*.tif") do mkdir "%DestFolder%\%%~nJ" 2>nul & move /Y "%%J" "%DestFolder%\%%~nJ\%%~nJ_%DateFolder:~7,8%%%~xJ" 1>nul
如果其中一个文件由于当前在应用程序中打开而无法移动,或者之前无法创建目标文件夹(具体取决于存储介质的文件系统),则最后一行可能会出现问题。最好是最后一行:
for /F "eol=| delims=" %%J in ('dir "%~1\*.tif" /A-D-L /B 2^>nul') do mkdir "%DestFolder%\%%~nJ" 2>nul & move /Y "%~1\%%J" "%DestFolder%\%%~nJ\%%~nJ_%DateFolder:~7,8%%%~xJ" 1>nul
这一行的缺点是从后台至少有一个 TIFF 文件的每个文件夹开始,再运行
cmd.exe
命令来输出不带路径的匹配文件名列表,包括那些被忽略的隐藏属性集在整个发布的批处理文件的最后一行中通过 FOR 。 FOR /D 还忽略具有隐藏属性集的目录。
注意: 如果目标目录中存在目标文件名具有只读属性的文件,则命令 MOVE 将提示批处理文件的用户,尽管使用其选项 /Y
如果只读属性仅应覆盖文件。由于命令行末尾有
1>nul
,因此看不到此提示。每当批处理文件停止移动文件时,请按 N键,以回答不可见的覆盖提示 NO。 要了解所使用的命令及其工作原理,请打开命令提示符
窗口,执行以下命令,并完整、仔细地阅读每个命令显示的帮助页面。
call /?
echo /?
exit /?
for /?
if /?
mkdir /?
move /?
set /?
setlocal /?
,了解无条件命令运算符的说明 &
通过减少执行期间读取的批处理文件中的行数,多次使用以加快批处理文件的处理速度两个
FOR循环。