在批处理文件中复制(移动)文件的快速方法

时间:2017-01-05 16:27:38

标签: windows performance batch-file copy move

我在一个目录中有大量文件需要验证。

问题是,文件浏览器花了太多时间加载文件列表,整个计算机变慢。

所以我编写了以下代码,通过将一定数量的文件(显示为%limit%并将为700)移动到编号文件夹(显示为%DirN%)来分组文件

for /f "tokens=1-2 delims=:" %%a in ('dir /b /a-d ^|findstr /n /v ".bat .cmd .txt"') do if %%a lss %limit% robocopy "%cd%" "%cd%\%DirN%" "%%b" /mov >nul

这段代码本身就像它设计的那样工作正常,但是发现了一个额外的问题:速度。

由于我正在处理占用20 GB磁盘的文件,因此代码似乎永远以这种方式移动文件。

有没有更快的方法来复制(移动)文件?

PS。我尝试了/move/xcopy命令,但没有看到太多差异。

由于有上下文请求,我附上完整的代码:

@echo off
pushd %~dp0

set DirN=-1
:Check_DirN
set LeftOver=
for /f "tokens=*" %%a in ('dir /b /a-d ^|findstr /v ".bat .cmd .txt"') do (set LeftOver=%%a)
if "%LeftOver%"=="" goto Done

set /a DirN+=1
if exist "%cd%\%DirN%" goto Check_DirN

:Create
md %DirN%

:Move
cls
echo Moving files to Directory %DirN%...
set /a limit=700+2
for /f "tokens=1-2 delims=:" %%a in ('dir /b /a-d ^|findstr /n /v ".bat .cmd .txt"') do if %%a lss %limit% robocopy "%cd%" "%cd%\%DirN%" "%%b" /mov >nul
goto Check_DirN

exit
:Done
del list.txt>nul 2>&1
echo Task Done!
pause>nul

评论

  1. 我使用set /a来调整因%limit%
  2. 而关闭的findstr /n /v
  3. 此脚本将编译为.bat文件,并将放入包含要排序的文件的文件夹中。
  4. 示例环境(最小化):

    在父文件夹中有1,500个文件,其子文件夹名为0,2和4。 该脚本将放在父文件夹内并执行。

    脚本要求:

    1. 仅当目录不存在时才创建从0开始的编号目录
    2. 将700个文件移动到新创建的目录。文件将被移动 即使文件数量少于700个。
    3. 重复任务1和2,直到剩下剩余文件为止 父目录。
    4. 脚本执行的示例结果:

      有一些名为0,1,2,3,4和5的子文件夹,其父文件夹中有一个脚本。 子文件夹1和3中将分别有700个文档。 子文件夹5中将有100个文档。 子文件夹0,2和4中没有变化。

2 个答案:

答案 0 :(得分:3)

我提供此作为Magoo的答案的替代品。我使用了您的初始RoboCopy命令,因为这是一个外部命令,删除了对外部FindStr的依赖关系,希望考虑到任何速度差异。

@Echo Off
If /I Not "%__CD__%"=="%~dp0" PushD "%~dp0" 2>Nul||Exit/B
SetLocal EnableDelayedExpansion
Set "DirN=-1"

:Check_DirN
Set/A "DirN+=1"
If Exist "%DirN%" GoTo Check_DirN
Set "limit=700"
For %%A In (*.bat *.cmd *.txt) Do (
    If Not Exist "%DirN%" MD "%DirN%"
    If /I Not "%%~nxA"=="%~nx0" RoboCopy . "%DirN%" "%%A" /MOV 1>NUL
    Set/A "limit-=1"
    If !limit! Lss 0 GoTo Check_DirN
)
Echo(Task Done!
Timeout -1 1>Nul

答案 1 :(得分:1)

@echo off
pushd %~dp0

set DirN=-1
:Check_DirN
set /a DirN+=1
if exist "%cd%\%DirN%" goto Check_DirN
md %DirN%
set /a limit=700
for /f "tokens=1* delims=:" %%a in ('dir /b /a-d ^|findstr /v ".bat .cmd .txt" ^|findstr /n "." ') do (
 if %%a gtr %limit% goto Check_DirN
 set /a limit=0
 echo(move "%%b" "%cd%\%DirN%\"
)
if %limit% neq 0 rd %DirN%
echo Task Done!
pause>nul

为了测试目的,所需的MOVE命令仅为ECHO在您确认命令正确后,将ECHO(MOVE更改为MOVE以实际移动文件。附加>nul以取消报告消息(例如1 file moved

首先,创建新目录。无需让for参与其中。

接下来,确定您的限制,然后选择并编号您的目录列表,并将每个文件依次移动到目的地。

达到文件限制时,请返回并创建新的目标目录。

请注意delayedexpansion被利用。 %limit%将在解析阶段由其值替换,如果移动任何文件,则将其设置为0。由于解析器已经完成了对其实际值的替换,因此这不会影响循环,但可以在循环结束后检测到"文件被移动"。

如果没有移动文件,则退出limit循环时for将保持非零,因此新创建的目录为空,可以删除。

我建议您尝试使用虚拟测试目录的较小限制来​​确保其正常工作。应该快得多。

[编辑 - 创建目录 检查后它还没有存在] [edit2- cascade 2 findstr s - 第一个排除扩展名,第二个是对行进行编号。尝试使用一个findstr将根据dir命令中的位置编号,因此排除的文件将被分配一个数字,但不会被转移;因此,移动的计数将短于limit

请注意,由于文件实际上不是move d echo(move,因此相同的文件列表将一遍又一遍地重复。调用move时,移动的文件显然不会在内部迭代中找到]