逍遥小书生 发表于 2020-10-30 20:29

[求助] 求帮写一个批量移动大量文件的脚本

我用比特彗星下载了约80W个种子文件,都在一个文件夹,每次打开文件夹的时候相当的费尽。
因此想分散存放到多级文件夹中。
文件名是40个字符的文件BitTorrent使用的散列指,字符是16进制用的0-9和a-f。
我的目的是使用3级目录,然后每个目录大约200个文件。
举个例子,305b64a9eba15847f133d5696ac47f661c629c3f.torrent,存放到目录3下的目录0下目录5下面。
我目前的批处理如下:
@echo off
setlocal enabledelayedexpansion
for %%a in (*.torrent) do (
    set "NameStr=%%~a"
    move "%%~a" "!NameStr:~ 0,1!\!NameStr:~ 1,1!\!NameStr:~ 2,1!"
)这个批处理能用,但是有问题。在运行中,非常消耗内存,一段时间内存就爆了。
因此我想求个能每移动约1000个文件就能暂停一会的脚本。
我自己弄了好几个方法都无法成功。


我当前的设想是用双循环,外层循环变量赋初值,进入内层循环,开始寻找文件并移动,变量自增。
接着内层循环判断变量是否超过1000,超过后转到外层循环,这时程序暂停一段时间。
然后变量重新赋初值,进入内层循环处理。


网上推荐的批处理延迟是直接调用ping命令,
ping 127.0.0.1 -n 1
如果只ping一次,延迟不太够,两次的话延迟又太高了,太浪费时间了。


我对批处理一窍不通,希望有高手帮一下。


逍遥小书生 发表于 2020-11-2 22:22

我自己解决了,我最开始定义使用数字变量的时候出错了。
批处理中,设定每操作一万个文件,暂停一会。
我自己测试的时候,内存还是会慢慢增长,必须要中断一下。
最终的批处理如下:
@echo off
setlocal enabledelayedexpansion

set /a movecount = 0
set /a movewan = 0
set /a moveyi = 0

for %%a in (*.torrent) do (
    set "NameStr=%%~a"
    if not exist "!NameStr:~ 0,1!\!NameStr:~ 0,2!\!NameStr:~ 0,3!" (
      md "!NameStr:~ 0,1!\!NameStr:~ 0,2!\!NameStr:~ 0,3!"
      echo Dir "!NameStr:~ 0,1!\!NameStr:~ 0,2!\!NameStr:~ 0,3!" have made !
    )
   
    move "%%~a" "!NameStr:~ 0,1!\!NameStr:~ 0,2!\!NameStr:~ 0,3!\"
    set /a movecount += 1

    if !movewan! gtr 0 (
      if !movecount! EQU 9999 (
            set /a movewan += 1
            echo Another 10,000 files have moved !
            set /a movecount = 0
            TIMEOUT /T 30
      )   
      if !movewan! EQU 9999 (
            set /a moveyi += 1
            echo 100,000,000 files have moved !
            set /a movewan = 0
            TIMEOUT /T 30
      )
    ) else (
      if !movecount! EQU 9999 (
            set /a movewan += 1
            echo 10,000 files have moved !
            set /a movecount = 0
            TIMEOUT /T 30
      )
    )

)

set /a movet = moveyi*100000000+movewan*10000+movecount
echo The number of moved files is : !movet!

endlocal

原来是豆芽 发表于 2020-11-3 09:20

你这, 大佬{:3_149:}霍茶{:3_192:}

逍遥小书生 发表于 2020-11-5 15:12

本帖最后由 逍遥小书生 于 2020-11-5 15:13 编辑

doya520 发表于 2020-11-3 09:20
你这, 大佬霍茶
:lol,我知道你想要什么。目前100W+,那个种子市场真的很厉害,虽然下载的种子基本都没源了。

逍遥小书生 发表于 2020-11-5 15:13

最后,我用goto加循环解决了问题,使用goto循环不会导致内存暴涨。可惜的是整个bat还是有瑕疵,中间在把子目录下的文件移动到总目录的时候会报错,但是能继续运行。

@echo off
setlocal enabledelayedexpansion
set /a ccount=0
set /a mcount=0
set /a mt=0
set /a sc=0
set key_1=A
set key_2=B
set key_3=C
set mkey_4=D

:start
cls
echo ------------------------------
echo 1: 汇集文件到总目录
echo 1:   Collect files
echo 2: 分离文件到多级子目录
echo 2:   Separate files
echo 3: 退出程序
echo 3:   Quit
echo ------------------------------
echo=
timeout 1 > nul
echo 你想执行那种操作?
echo What kind of operation do you want to perform?
echo=
echo 请输入“1”执行汇集,“2”执行分离,“3”退出程序。
echo Please enter 1 for collect , 2 for separate , 3 for quit program:
echo=
goto choose

:choose
echo 输入一个选项,输入回车后结束输入:
set /p inp=Input a number , type enter to end input:
echo=
if defined key_%inp% (
    goto :!key_%inp%!
) else (
    set /a sc+=1
    goto repeat   
)

:A
    echo 你选择了汇集文件,开始执行命令.
    echo Your select is to collect ,command start.
    timeout 1 > nul
    goto collect
:B
    echo 你选择了分离文件,开始执行命令.
    echo Your select is to separate ,command start.
    timeout 1 > nul
    goto separate
:C
    echo 你选择了退出,开始执行命令.
    echo Your select is to quit ,command start.
    timeout 1 > nul
    goto end
:D
    goto start
   
:repeat
if !sc! leq 2 (
    echo 选项不存在,请重新输入。
    echo Your choice does not exist, please enter again。
    echo=
    timeout 1 > nul
    goto choose
) else (
    echo 你输入了错误的字符,程序现在退出!
    echo You entered the wrong key and the program now exits.
    timeout 1 > nul
    goto end
)

:collect
echo %CD%
pause
for %%d in (0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f) do (
::    echo HH
::    pause
    cd %%d
    for %%c in (0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f) do (
::      echo JJJ
::      pause
      cd %%d%%c
      for %%b in (0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f) do (
::            echo %CD%
            cd %%d%%c%%b
::            pause
            for%%a in (%CD%\%%d\%%d%%c\%%d%%c%%b\*.torrent) do (
                pause
               set /a ccount+=1
               set "NameStr=%%~a"
               move "%%~a" "%CD%"
            )
            cd ..
::             pause
::            goto end
      )
      cd ..
    )
    cd ..
)

if !ccount! neq 0 (
    echo 汇集文件完成。
    echo Collection is complete .
    echo=
    echo 合计移动了 !ccount! 个文件。
    echo !ccount! files have moved .
    echo=
    timeout 1 > nul
    goto menu
::    exit /b 1
) else (
    goto nothing
::    exit /b 2
)

:separate
::pause
for %%s in (*.torrent) do (
    set "NameStr=%%~s"
    if not exist "!NameStr:~ 0,1!\!NameStr:~ 0,2!\!NameStr:~ 0,3!" md "!NameStr:~ 0,1!\!NameStr:~ 0,2!\!NameStr:~ 0,3!"
    move "%%~s" "!NameStr:~ 0,1!\!NameStr:~ 0,2!\!NameStr:~ 0,3!\"
    set /a mcount+=1
    if !mcount! equ 10000 (
      echo 一万个文件移动完成。
      echo 10000 files have moved .
      timeout 5 > nul
      goto mup
    )
    goto separate   
)
::pause
goto scount   

:mup
set /a mt+=1
set /a mcount=0
goto separate

:scount
if !mcount! gtr 0 (
    goto mend
) else if !mt! gtr 0 (
    goto mend
) else (
    goto nothing
)

:mend
set /a mt=mt*10000
set /a mt=mt+mcount
echo 分离文件完成。
echo Separation is complete .
echo=
echo 合计移动了 !mt! 个文件。
echo !mt! files have moved .
echo=
timeout 1 > nul
goto menu

:nothing
echo 没有一个文件被操作.
echo No file has been operated.
echo=
timeout 1 > nul
goto menu

:menu
echo 是否重新开始?
echo Do you want to start again?
echo=
echo 输入"4"重新开始任务,输入其他结束程序,输入回车后结束输入:
set /p minp=Input 4 to restart , other to exit , type enter to end input:
echo=
if defined mkey_%minp% (
    goto :!mkey_%minp%!
) else (
    goto C
)

:end
echo 程序将在5秒后退出。
echo exit
timeout /t 5
exit
页: [1]
查看完整版本: [求助] 求帮写一个批量移动大量文件的脚本