Recently there where a question about moving many files with user predefined file type extension from one folder to many different folders that are instantly created upon a key string (YEAR) inside the name of the files. Also, when moving to newly created folders, files should be saved without user predefined file type extension (File name 2016.myextension.txt > File name 2016.txt). I have been interested into this problem, so I have created simple cmd program.
There Are Two Problems :
Program works correctly but it is too slow.
Is there any way to make it run faster?
The ECHO %TIME% command inside the for /l %%A in (1900,1,2099) loop, look at the end of the program code, always returns the same time value.
Is there any way to make it return correct current system time?
Here is the program code :
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
According to all answers given to my question I have made this program that completely solves the problem. Any suggestions for improvement are welcome.
@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
Just another idea to try to avoid calling findstr. While not bulletproof (only tested against a listing of the first few pages in a torrent movie site), this could handle the task in reasonable times.
The main idea is to remove the numbers from the file name (using them as delimiters in a for /f loop) and use the remaining characters as delimiters in another for /f, to only leave the numbers in the file name. The set of numbers are then iterated to determine if they match the required year range. If a year is found, then the script will echo to console the move command to execute. If the output is correct, remove the echo to perform the move operations.
@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
It looks like you are running findstr 199 times. I'd expect a speed increase by removing the for /l loop and using a single findstr instance Perhaps:
findstr /r "\<19[0-9][0-9] \<20[0-9][0-9]"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With