I have 16 files that I would like to group together so that there are 3 files per folder (the remainder would be placed in a separate folder). Essentially the files have a date string that I would like to use to group the files. For example, 201301 is January 2013. Is there a way to create a batch program or otherwise to do something like the following:
1) Create list of all strings of the same form as 201301. This can be done by choosing a starting point (in this case 11 characters into the title) to start counting from and then count to 5.
Would something like this fit the bill?
2) Sort these strings from smallest to largest using something like:
:startSort // Set our upper "array bound"
set /a total=count-1
:RestartSort // Restart the sort from the beginning
set /a count=1
:sortLoop
set /a next=%count%+1 // Swap n and n+1
call :swap %count% %next%
set /a count=count+1
if "%swapped%" == "true" goto :RestartSort // If the variables were swapped,
// start again
if "%count%" == "%total%" goto :output // If we're done,
// output the results
goto :sortLoop // Back to the start to
// swap the next two
3) Count to three and then create a folder in which to store the three files
4) store the three files
5) continue until no more files remain
The only issue I have with this setup is that it will probably not know what to do when it gets to the last file that has no other files to be grouped with. Is there a way to get it to account for this - some way it knows it's hit the end of the list?
For reference, the file names are of the form 12345_ABCDE_20130101_20130101, and the folder names would simply be something like 201301-201303 (to use the same example values).
code example:
#ECHO OFF &SETLOCAL disableDelayedExpansion
SET /a Counter=0
SET /a FilesPerFolder=3
FOR /f "delims=" %%a IN ('DIR /b /a-d /on "%cd%\test\*"') DO (
SET /a Test=Counter%%FilesPerFolder
SET /a TargetFolder=Counter/FilesPerFolder
SETLOCAL enableDelayedExpansion
MD "%cd%\test\Folder!TargetFolder!" 2>nul
MOVE "%cd%\test\%%~a" "%cd%\test\Folder!TargetFolder!" >nul
ENDLOCAL
SET /a Counter+=1
)
Related
If I have a directory full of text files such as
01.text.sql
02text.sql
3text.sql
how would I return the file name with the highest integer e.g. 3.text.sql? As you can see the numbers might not be prefixed with 0 and might be missing a . after the integer. I know I have to loop through the directory with something like this
Choose Highest Numbered File - Batch File
however, this does not take into account different file name formats. Is there any way a batch script can loop through a directory and automatically pull the file with the highest integer or do I have to store the file names and compare them with each other in a separate loop?
Currently I have something like this but it returns 3text instead of just 3
SETLOCAL enabledelayedexpansion
SET max=0
FOR %%x in (*.sql) DO (
SET "FN=%%~nx"
SET "FN=!FN:*-=!"
IF !FN! GTR !max! SET max=!FN!
)
ECHO Highest script number is %max%
Updated loop:
SETLOCAL enabledelayedexpansion
SET scriptmax=0
FOR %%x in (*.sql) DO (
SET "FN=%%~nx"
SET a=1000!FN!
SET /A FN=a %% 1000
IF !FN! GTR !max! SET max=!FN!
)
set /A a=b will interpret everything in b up to the first non numeric character as a number, so
set FN=03text.txt
set /A a=FN
will set %a% nicely to 3. But we have an additional problem here: Numbers prefixed with a 0 will be interpreted as octal, so 08 and 09 are illegal. To fix this:
set FN=09text.txt
set t=1!FN!
set /A a=t-100
will yield 9.
However, this will only work if you know how many digits to expect, maybe you have to check for a leading zero first (if "%FN:~0,1%" == "0" ...), and/or even chop off leading zeroes (set FN=%FN:~1%)
Edit: a better way:
set FN=09text.txt
set a=1000!FN!
set /A FN=a %% 1000
will work for anything up to 999.
Hi I would like to create a batch file which makes n amount of folders and moves them to a specified dir. something like make folders {00001-00009} to put it bluntly. I don't want to manually put each number in and I would like to be able to exclude numbers as well.
so far I have tried this code below. I get the 5 folders made in C:\source\
and I am able to dictate how they are named to an extent, by changing j=5 to whatever integer, however sometimes the file makes folders from 00256-003372 instead of what I specified. this happens when I change j to j=256 and run the program.
echo off
cd C:\source\ :: I included this because for some reason folder 1 copied to root
SET /a j=1
:floop
IF %j%==5 GOTO END
md 00%j%
cd 00%j%
SET /a j=%j%+1
cd C:\source\
GOTO FLOOP
:end
The other way I did this was to manually input each number in a .bat file such as below. which works fine but I have to make a line for each folder.
md C:\Device_Numbers_Folder\00001
md C:\Device_Numbers_Folder\00002
P.S I named the dir file source because I am running a bunch of .bat files with CALL and this is the source part.
I think you want something like this:
#echo off
setlocal EnableDelayedExpansion
::CD "C:\source\"
::only change these three lines
set "start=1"
set "amount=5"
set "length=5"
set "exclude=4,5"
set "excluded=0"
FOR %%G IN (%exclude%) DO (set /a "excluded+=1")
set /a "last=%start%+%amount%+%excluded%"
for /l %%i in (%start%,1,%last%) do (
set "skip=0"
FOR %%G IN (%exclude%) DO (if "%%i"=="%%G" set "skip=1")
if !skip! equ 0 (
set "folderName=0000000000%%i"
set "folderName=!folderName:~-%length%!"
md "!folderName!"
)
)
In this start is the first number, amount is the amount of folder it needs to create, and length is the lenght of the names of the new files, so 1 with length 5 becomes 00001. Exclude is an comma seperated list of all the numbers not allowed
Inside a directory c:\configs I have files with various extensions including the extension .rac. I need a script for the Windows command prompt that looks inside c:\configs for the names of the files that end with the extension .rac, ignoring other extensions. Then of all the names that end with .rac extension the script must choose a random one and process it with the command c:\programs\submit.exe namerandom.rac.
For example, suppose that random .rac file is called mosaic.rac, then the script executes the command c:\programs\submit.exe mosaic.rac. Of course the mosaic.rac name changes each time the script is runs because it is a random selected from the all the .rac files found.
Anyone have an idea in how to do and that can put example code?
#echo off
setlocal EnableDelayedExpansion & set n=0
for /f "delims=" %%a in ('dir /b /A-D "*.rac"') do (
set "f=%%a" & set "f[!n!]=!f!" & set /a "n+=1")
set /a c=%random% %% n
echo !f[%c%]!
Explanation:
Line #4: it make a pseudo array in f with n incremented by 1
Line #5: it take a random number between 0 and the total count of files called n with the help of: %random% modulo n
In this way, this creates a number of variables automatically according to their position then %random% %% n picks one.
You might as well picks some manually like this:
echo !f[0]! !f[1]! !f[2]! !f[3]! !f[4]! !f[5]! ...
To accomplish that, you may use the following...
Firstly, to get all .rac files, use the dir command. The /B switch specifies to output only a bare file list without any headers nor footers. If you want to search the given directory recursively, add the /S switch:
dir /B "C:\configs\*.rac"
Secondly, you need to count the number of returned .rac files. You can use a for /F loop (parsing the output of dir /B) together with set /A for that:
set /A COUNT=0
for /F "delims=| eol=|" %%L in (
'dir /B "C:\configs\*.rac"'
) do (
set /A COUNT+=1
)
Thirdly, you need to compute a random number in the applicable range. The built-in variable RANDOM retrieves a random number from 0 to 32767, so we need a little maths. The result will be a number from 0 to %COUNT% - 1:
set /A RNDNUM=%RANDOM%%%COUNT
Fourthly, you can use another for /F loop with the skip option to select a random file (we skip the previously calculated number RNDNUM of lines).
The if statement ensures that no skip option is provided in case the random number is 0.
The goto command ensures that only the selected file is passed to submit.exe. If you omitted it, every file after the selection would be passed over to submit.exe too, one after another:
if %RNDNUM% gtr 0 (
set SKIP=skip=%RNDNUM%
) else (
set SKIP=
)
for /F "%SKIP% delims=| eol=|" %%L in (
'dir /B "C:\configs\*.rac"'
) do (
start "" /WAIT "submit.exe" "%%~L"
goto :CONTINUE
)
:CONTINUE
Put together those parts to get the final script.
Type each command and append /? in command prompt to get the respective help text displayed.
I have a folder with thousands of sub-folders, each containing one video file, and one subtitle file, like this:
Each of those text files (.srt) are subtitle files intended to display the filename (without extension) at the beginning and end of each video. For example, the contents of Track Two - Track Two.srt are:
1
00:00:00,500 --> 00:00:03,500
Track Two - Track Two
2
00:00:00,000 --> 00:00:00,000
Track Two - Track Two
Thanks to some serious StackHeads, I've been able to automate the creation of the text files by running the following batch script in the ./media/ parent directory:
for /R %%f in (*.flv *.mp4) do (
echo(1
echo(00:00:00,500 --^> 00:00:03,500
echo(%%~nf
echo(
echo(2
echo(00:00:00,000 --^> 00:00:00,000
echo(%%~nf
) > "%%~dpnf.srt"
Now all I have left to do is update the sixth line of each .srt file to make it show the filename for three seconds just prior to the end of the video. Ideally, the first numerical value would be 3.5 seconds prior to the end of the video, and the second value would be .5 seconds prior to the end.. and to make it even harder, it has to be in the Russian timecode .srt files use.
For example, if Track Two - Track Two is 01:36 long, the 6th line of Track Two - Track Two.srt should read:
00:01:32,500 --> 00:01:35,500
I can generate a text list of all of the video lengths, like this:
..and as long as I keep the folder names strictly numbered, they'll line up every time.
Is there any way to pull out the video lengths from the text file times.txt (assuming the order is perfect), and update the 6th line of each .srt file in Russian timecode format to make it display the title prior to the end the video file it references?
Any help is graciously appreciated!!
Also.. thanks again to dbenham, MC ND, payeli for your help before!! You're the best!
#ECHO OFF
SETLOCAL
SETLOCAL ENABLEDELAYEDEXPANSION
FOR /f "skip=1tokens=2,3,11delims=," %%a IN (list.csv) DO (
SET ttrack=%%a
SET videoname=%%~nb
set to_file="%%c\%%~nb.srt"
CALL :process
)
GOTO :EOF
:process
FOR /f "tokens=1-3delims=:" %%r IN ("%ttrack%") DO (
SET /a hr=10%%r
SET /a mi=1%%s
SET /a se=1%%t
)
CALL :subs 1
SET endtime=%hr:~-2%:%mi:~-2%:%se:~-2%,500
CALL :subs 3
SET starttime=%hr:~-2%:%mi:~-2%:%se:~-2%,500
echo(1
echo(00:00:00,500 --^> 00:00:03,500
echo(!videoname!
echo(
echo(2
echo(%starttime% --^> %endtime%
echo(!videoname!
ECHO(sent to %to_file%
GOTO :eof
::
:: subtract %1 seconds from hr,mi,se
::
:subs
SET /a se-=%1
IF %se% geq 100 GOTO :EOF
SET /a se+=60
SET /a mi-=1
IF %mi% geq 100 GOTO :EOF
SET /a mi+=60
SET /a hr-=1
GOTO :eof
Not hard.
All you'd need to do if this seems appropriate is to change
echo(1
...
echo(%videoname%
ECHO(sent to %to_file%
to
(
echo(1
...
echo(%videoname%
)>%to_file%
I have this code, where I want to test "counting". Counting does not work.
Code:
set "Myvar=Hello"
set #=%MyVar%
set strlen=0
:loop
if defined # (set #=%#:~1%&set /A strlen += 1&goto loop)
echo LEN: %strlen%
SET /A tabscount=(40-%strlen%)/8
echo Tabs count: %tabscount%
echo counting...
FOR /L %%G IN (0,1,%%tabscount) DO echo %%G
pause
And second problem is I would like to add tabs to end of string Myvar so many times as the tabscount value is.
How to do the adding in DO block? Should something like this work? SET "tabs=% %" Or rather SET "Myvar.= "?
Edited:
I repaired the %%tabscount
Your counting FOR /L loop is missing percents around the tabscount variable
FOR /L %%G IN (0,1,tabscount) DO echo %%G
To append tabs is no different than appending any other string. Tabs are difficult to differentiate from spaces simply by looking at the code. I recommend defining a TAB variable so you only have to worry about the tab literal in one place.
If you were just doing a single append, then you could simply use
set "TAB= "
set "MyVar=%MyVar%%TAB%"
But you want to use a loop to append multiple tabs, and %MyVar% will only be expanded once within a loop. So you need to do something to access the current value within the loop. You have multiple options:
1) Use CALL SET to get an extra parse for each iteration: (relatively slow and potentially unsafe)
for /l %%G in (0 1 %tabscount%) do call set "MyVar=%%MyVar%%%TAB%"
2) Use a GOTO loop instead of FOR /L. The IF statement will be reparsed each iteration, so it will work. (relatively slow, but a bit safer than option 1)
:appendLoop
if %tabscount% gtr 0 (
set "MyVar=%MyVar%%TAB%"
set /a tabscount-=1
goto :appendLoop
)
3) Use delayed expansion so that you get the value at execution time instead of parse time. (much faster and always safe)
setlocal enableDelayedExpansion
for /l %%G in (0 1 %tabscount%) do set "MyVar=!Myvar!%TAB%"
There are other variations.
Note that SET /A is the one situation where you do not need percents around numeric variables. There is nothing wrong with what you have, but you could also write the SET /A statement as
set /a tabscount=(40-strlen)/8