在批处理文件中复制(移动)文件的快速方法
Fast methods to copy(move) files in batch file
我在一个目录中有大量文件需要验证。
问题是,文件资源管理器加载文件列表的时间太长,我的整个计算机都变慢了。
所以我写了下面的代码通过将一定数量的文件(显示为%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
评论
- 我使用
set /a
来调整由于 findstr /n /v
而关闭的 %limit%
- 此脚本将被编译为 .bat 文件,并将放入包含要排序的文件的文件夹中。
示例环境(最小化):
父文件夹中有 1,500 个子文件夹名为 0,2 和 4 的文档。
脚本将被放置在父文件夹中并被执行。
脚本要求:
- 仅当目录不存在时才从 0 开始创建编号目录
- 将 700 个文件移动到新创建的目录。文件将被移动
即使文件数量少于 700.
- 重复任务 1 和 2 直到没有剩余的文件
父目录。
脚本执行的示例结果:
父文件夹中有名为 0、1、2、3、4 和 5 的子文件夹以及脚本。
子文件夹 1 和 3 中各有 700 个文档。
子文件夹 5 中将有 100 个文档。
子文件夹 0、2 和 4 不会发生变化。
@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
ed 用于测试目的。 确认命令正确后,将ECHO(MOVE
更改为MOVE
以实际移动文件。附加 >nul
以禁止报告消息(例如 1 file moved
)
首先,创建新目录。不需要涉及for
。
接下来,建立您的限制,然后 select 对您的目录列表进行编号,然后依次将每个文件移动到目的地。
当达到文件限制时,返回并创建一个新的目标目录。
请注意 delayedexpansion
已被利用。 %limit%
将在解析阶段被替换为它的值,并且如果有任何文件被移动将被设置为 0。由于其真实值的替换已经由解析器完成,这不会影响循环,但可以在循环完成后检测到意味着 "a file was moved".
如果没有文件被移动,那么 limit
将在退出 for
循环时保持非零,因此新创建的目录是空的并且可以被删除。
我建议您在虚拟测试目录上使用较小的限制来尝试此操作,以确保它有效。应该快得多。
[编辑 - 创建目录 后 检查它不存在]
[edit2- cascade 2 findstr
s - 第一个排除扩展名,第二个对行编号。尝试使用一个findstr
会根据dir
命令中的位置编号,所以被排除的文件会分配一个编号,但不会被转移;因此 count-moved 将缺少 limit
请注意,由于文件实际上不是 move
d 且 echo(move
就位,因此将一遍又一遍地重复相同的文件列表。当调用move
时,移动过的文件显然不会在字母迭代中找到]
我提供这个作为 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
我在一个目录中有大量文件需要验证。
问题是,文件资源管理器加载文件列表的时间太长,我的整个计算机都变慢了。
所以我写了下面的代码通过将一定数量的文件(显示为%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
评论
- 我使用
set /a
来调整由于findstr /n /v
而关闭的 - 此脚本将被编译为 .bat 文件,并将放入包含要排序的文件的文件夹中。
%limit%
示例环境(最小化):
父文件夹中有 1,500 个子文件夹名为 0,2 和 4 的文档。 脚本将被放置在父文件夹中并被执行。
脚本要求:
- 仅当目录不存在时才从 0 开始创建编号目录
- 将 700 个文件移动到新创建的目录。文件将被移动 即使文件数量少于 700.
- 重复任务 1 和 2 直到没有剩余的文件 父目录。
脚本执行的示例结果:
父文件夹中有名为 0、1、2、3、4 和 5 的子文件夹以及脚本。 子文件夹 1 和 3 中各有 700 个文档。 子文件夹 5 中将有 100 个文档。 子文件夹 0、2 和 4 不会发生变化。
@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
ed 用于测试目的。 确认命令正确后,将ECHO(MOVE
更改为MOVE
以实际移动文件。附加 >nul
以禁止报告消息(例如 1 file moved
)
首先,创建新目录。不需要涉及for
。
接下来,建立您的限制,然后 select 对您的目录列表进行编号,然后依次将每个文件移动到目的地。
当达到文件限制时,返回并创建一个新的目标目录。
请注意 delayedexpansion
已被利用。 %limit%
将在解析阶段被替换为它的值,并且如果有任何文件被移动将被设置为 0。由于其真实值的替换已经由解析器完成,这不会影响循环,但可以在循环完成后检测到意味着 "a file was moved".
如果没有文件被移动,那么 limit
将在退出 for
循环时保持非零,因此新创建的目录是空的并且可以被删除。
我建议您在虚拟测试目录上使用较小的限制来尝试此操作,以确保它有效。应该快得多。
[编辑 - 创建目录 后 检查它不存在]
[edit2- cascade 2 findstr
s - 第一个排除扩展名,第二个对行编号。尝试使用一个findstr
会根据dir
命令中的位置编号,所以被排除的文件会分配一个编号,但不会被转移;因此 count-moved 将缺少 limit
请注意,由于文件实际上不是 move
d 且 echo(move
就位,因此将一遍又一遍地重复相同的文件列表。当调用move
时,移动过的文件显然不会在字母迭代中找到]
我提供这个作为 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