cmd编程中的速度和时间问题

时间:2016-09-05 20:06:08

标签: windows batch-file cmd

最近出现了一个问题,即将用户预定义文件类型扩展名的许多文件从一个文件夹移动到许多不同的文件夹,这些文件夹立即在文件名称内的密钥字符串(YEAR)上创建。此外,当移动到新创建的文件夹时,应保存文件而不使用用户预定义的文件类型扩展名(文件名2016.myextension.txt>文件名2016.txt)。我一直对这个问题感兴趣,所以我创建了简单的cmd程序。

有两个问题:

程序运行正常,但速度太慢。

有没有办法让它跑得更快?

ECHO %TIME%循环中的for /l %%A in (1900,1,2099)命令,查看程序代码的结尾,始终返回相同的时间值。

有没有办法让它返回正确的当前系统时间?

以下是程序代码:

rem program start
rem 
rem use double % for cmd line parameters when generating .bat
rem use single % for cmd line parameters for direct cmd execution 
rem use ^ for cmd line brake
rem
rem
rem change command prompt attributes
rem 
echo off
mode con:cols=80 lines=40
title Program
color 0A
cls
echo.
echo Program start running at... %TIME%
echo.
rem set local variables value 
setlocal EnableDelayedExpansion EnableExtensions
set old_folder_path=C:\Torrent_files\
set new_folder_path=C:\Torrent_movies\
set folder_path=C:\Torrent_movies\Year_
set f1=.
set f2=.
set list_path_extension=C:\Torrent_movies\Torrent_list.txt
set extension=.torrent
rem create root folder for new movie folders
if not exist %new_folder_path% (echo Creating Torrent_movies folder... && ^
md %new_folder_path% && echo Done at... %TIME%)
echo.
rem set current directory to new_folder_path
cd %new_folder_path%
rem create new list 
rem of torrent files inside the folder
echo Creating empty List of files...
echo. > %list_path_extension%
echo Done at... %TIME%
echo.
rem Fill List of files
echo Filling List with file names...
for /r %old_folder_path% %%T in (*%extension%) do (^
set f1=%%T && ^
set f2=!f1:%old_folder_path%=! && ^
echo !f2! >> %list_path_extension%)
echo Done at... %TIME%
echo.
rem search for year inside file paths saved in Torrent_list.txt file
rem by using for loop, where value of cmd parameter 
rem A goes from year 1900 up to 2099, 
rem if there is match between string value of A as a regular expression, 
rem and string inside file path, create new folder for that year
rem else skip
echo Moving files
for /l %%A in (1900,1,2099) do (^
for /f "tokens=*" %%G in ('findstr /r "\<%%A" %list_path_extension%') do (^
(if exist %folder_path%%%A (echo.) ^
else (md %folder_path%%%A && echo %folder_path%%%A   Folder created)) && ^
echo Moving file %%G && set f1=%%G && set f2=!f1:%extension%=! && ^
move "%old_folder_path%%%G" "%folder_path%%%A\!f2!" && echo Done at... %TIME% && echo.))
rem list current directory to show changes
dir %new_folder_path%
echo.
echo Program finished at...%TIME%
echo.
pause
rem program end

根据我的问题给出的所有答案,我已经完成了这个程序,完全解决了这个问题。欢迎任何改进建议。

@echo off
    rem
    rem Program solves next problem :
    rem
    rem Inside one folder there are many files.
    rem Files have different file type.
    rem File name can contain :
    rem only one or none, YYYY (year) string,
    rem key word or user predefined file type 
    rem
    rem exmpl :
    rem 
    rem Root folder path : 
    rem
    rem C:\My_files_type_of_backup
    rem
    rem Folder contains :
    rem
    rem File 1 video (1998).backup.avi
    rem File 2 painting 2016.backup.bmp
    rem File 3 mp3 1901.backup.wav
    rem File 4 My Bigraphy 2000.backup.txt
    rem File 5 mp4 19.wav
    rem File 6 My file 2000.txt
    rem File 7 List of files.rtf

    rem
    rem Program must select all files which names contains
    rem YYYY string, year from 1900-2099 and 
    rem selected key word, 
    rem or user predefined file type entered by keyboard and
    rem selected file type extension entered by keyboard
    rem
    rem Program then creates new folders 
    rem with YYYY string inside folder name and
    rem moves files to newly created folders 
    rem according to year inside file name
    rem
    rem Depending on the options selected 
    rem at the beginning of the program,
    rem program moves only files that
    rem have selected key word inside file name and
    rem key word can be deleted from 
    rem file name before moving
 
    rem After program execution this would be result :
    rem
    rem    options selected : 
    rem
    rem    key_word = .backup, 
    rem    erase key word = Yes
    rem    file type = .*
    rem
    rem Root folder path : 
    rem
    rem C:\My_files_type_of_backup
    rem
    rem Folder contains new folders with files in it:
    rem
    rem Year 1901
    rem 		File 3 mp3 1901.wav
    rem Year 1998
    rem 		File 1 video (1998).avi
    rem Year 2000
    rem 		File 4 My Bigraphy 2000.txt
    rem 		File 6 My file 2000.txt
    rem Year 2016
    rem 		File 2 painting 2016.bmp
    rem 
    rem File 5 mp4 19.wav
    rem File 7 List of files.rtf
    rem 
    rem


    rem
    rem CMD attributes
    rem
    mode con:cols=80 lines=40
    title Program move files
    color 0A
    cls
    echo.
    echo Program started at ... %TIME%
    rem
    rem Local variables
    rem
    setlocal enableextensions enabledelayedexpansion
    set f=0
    set f1=.
    set f2=.

    rem
    rem Program options
    rem
    set /p key_word=Please enter key word [exmpl .backup] : || set key_word=*
    echo.
    echo Selected key word : %key_word%
    echo.
    set /p erase=Do You wish to erase key word from file name [Enter=No]: || set erase=n
    echo.	
    set /p file_type=Please enter file type  exmpl .* or .bmp : || set file_type=.*
    echo.
    echo Selected file type : %file_type%
    echo.

    rem	
    rem Find all files inside folder that contains 
    rem YYYY string (year 1900-2099) and 
    rem selected key word inside file name
    rem
    for %%# in (*%key_word%*%file_type%) do (
        for /f "tokens=1-26 delims=0123456789 " %%a in ("%%~n#") do (
            set "delims=%%a%%b%%c%%d%%e%%f%%g%%h%%i%%j%%k%%l%%m%%n%%o%%p%%q%%r%%s%%t%%u%%v%%w%%x%%y%%z"
            call :extractYear && (
                for %%y in ("!year!") do (

                
                    rem Create new folder
                    if not exist "%%~y\" md "Year %%~y"
                    
                    rem Erase selected key word from file name
                    rem if erase option is set to 'Yes' and
                    rem key word is not empty string
                    rem
                    set f1=%%~#
                    set f2=!f1!
                    if %erase% neq n if %key_word% neq *  (set f2=!f1:%key_word%=!)

                    rem
                    rem Move file
                    rem
		    echo Moving "!f1!" to folder "Year %%~y\!f2!"
		    move "!f1!" "Year %%~y\!f2!"

                    rem count number of moved files
                    set /a f=f+1     
                )
            )
        )
    )

    echo.
    if %f% equ 0 (echo There are no files that match criteria for moving) else (echo %f% files moved)
    echo.
    echo Program finished at ... %TIME%
    pause
    goto :eof

:extractYear
    for %%a in ("") do for /f "tokens=1-26 delims=%delims% " %%a in ("%%~n#") do for %%# in (
        %%~z %%~y %%~x %%~w %%~v %%~u %%~t %%~s %%~r %%~q %%~p %%~o %%~n
        %%~m %%~l %%~k %%~j %%~i %%~h %%~g %%~f %%~e %%~d %%~c %%~b %%~a 
    ) do if %%~# geq 1900 if %%~# leq 2099 (
        set "year=%%~#"
        exit /b 0
    )
    exit /b 1

3 个答案:

答案 0 :(得分:1)

看起来你正在运行findstr 199次。我希望通过删除for / l循环并使用单个findstr实例来提高速度 也许:

findstr /r "\<19[0-9][0-9] \<20[0-9][0-9]"

答案 1 :(得分:1)

尝试避免调用findstr只是另一个想法。虽然不是防弹的(仅针对洪流电影网站中前几页的列表进行测试),但这可以在合理的时间内完成任务。

主要思想是从文件名中删除数字(在for /f循环中使用它们作为分隔符),并将其余字符用作另一个for /f中的分隔符,只留下数字文件名。然后迭代该组数字以确定它们是否匹配所需的年份范围。如果找到一年,则脚本将回显以控制move命令执行。如果输出正确,请移除echo以执行move操作。

@echo off
    setlocal enableextensions disabledelayedexpansion

    for %%# in (*.torrent) do (
        for /f "tokens=1-26 delims=0123456789 " %%a in ("%%~n#") do (
            set "delims=%%a%%b%%c%%d%%e%%f%%g%%h%%i%%j%%k%%l%%m%%n%%o%%p%%q%%r%%s%%t%%u%%v%%w%%x%%y%%z"
            call :extractYear && (
                setlocal enabledelayedexpansion
                for %%y in ("!year!") do (
                    endlocal
                    if not exist "%%~y\" md "%%~y"
                    echo move "%%~#" "%%~y"
                )
            )
        )
    )
    goto :eof

:extractYear
    for %%a in ("") do for /f "tokens=1-26 delims=%delims% " %%a in ("%%~n#") do for %%# in (
        %%~z %%~y %%~x %%~w %%~v %%~u %%~t %%~s %%~r %%~q %%~p %%~o %%~n
        %%~m %%~l %%~k %%~j %%~i %%~h %%~g %%~f %%~e %%~d %%~c %%~b %%~a 
    ) do if %%~# geq 1900 if %%~# leq 2016 (
        set "year=%%~#"
        exit /b 0
    )
    exit /b 1

答案 2 :(得分:1)

简而言之,您必须在程序开头(或至少在循环之前)编写setlocal enabledelayedexpansion并使用!TIME!代替%TIME%来打印当前值而不是循环开始时的值。