中国DOS联盟论坛

China DOS Union

-- Unite DOS · Advance DOS · Grow DOS --
Union site: www.cn-dos.net Forum site: www.cn-dos.net/forum
Guest | Log in | Register | Members | Search | China DOS Union
中国DOS联盟论坛
The time now is 2026-09-13 22:14
47,812 topics / 349,916 posts / today 0 new / 48,268 members
DOS批处理 & 脚本技术(批处理室) » A question about randomly obtaining file names.
Printable Version  18,637 / 54
Floor1 voiL Posted 2006-07-26 19:27
中级用户 Posts 189 Credits 384
Runtime environment: XP SP2 CMD.

A friend asked me this question. I thought it was pretty interesting, but my skills are limited, so I can't write a batch file like this.

The problem is like this:

Conditions: the names obtained must be random, not too regular (they can't be completely ordered by size, name, creation date, etc.), and there must also be a quantity limit (take 100 files as an example). If it's sorting by size or name and so on, I can write that myself. What stumped me is the random part and the 100 files part here.

In an MP3 directory, I have N MP3 files (basically all named in Chinese). Now I want to use a batch file to randomly generate an M3U playlist, and then call WMP to play it, so as to achieve WMP random playback.

I can write all the other parts, it's just this one step of randomly obtaining the filenames that I can't write.

Not sure if anyone on the forum is interested. Please post some code if so.

[ Last edited by voiL on 2006-7-26 at 19:37 ]
Floor2 voiL Posted 2006-07-26 19:38
中级用户 Posts 189 Credits 384
Oh right, if BAT can't do it, then VBS can also be considered. Since I'm not familiar with VBS, I have no way to write it in VBS.
Floor3 namejm Posted 2006-07-26 19:40
荣誉版主 Posts 1,737 Credits 5,226 From 成都
  Using %random% and findstr /n should probably work. The main idea is to first use findstr /n to number the MP3 filename list, then use %random% to generate random numbers, and then list out the filenames represented by %random%. As for the details, I haven't thought them through yet, and I haven't written the actual code either. I'll just post the idea here first and see whether everyone has any better ideas.
Floor4 voiL Posted 2006-07-26 20:48
中级用户 Posts 189 Credits 384
Hehe, parameters like %random% are too abstruse. I still haven't fully figured them out, so I can't write it yet. Experts, please don't laugh at me.
Floor5 zh159 Posted 2006-07-26 20:53
金牌会员 Posts 1,467 Credits 3,687
Doesn't WMP or WINAMP already have a random play function? Doing it this way is a bit too roundabout, isn't it? ^_^
Floor6 voiL Posted 2006-07-26 21:00
中级用户 Posts 189 Credits 384
Originally posted by zxcv at 2006-7-26 20:53:
Doesn't WMP or WINAMP already have a random play function? Doing it this way is a bit too roundabout, isn't it? ^_^


What I'm interested in is not whether it can achieve random playback, but only how to achieve randomly obtaining filenames. Since I can't handle it myself, I had no choice but to come ask for advice.
Floor7 voiL Posted 2006-07-26 21:01
中级用户 Posts 189 Credits 384
I had also thought about sorting separately by name, date, and size, then taking the first part of the filenames from each and sorting them again by name. But that method can only be used once, because the names generated each time are still the same, so it can't achieve randomly obtaining filenames.
Floor8 zh159 Posted 2006-07-26 21:08
金牌会员 Posts 1,467 Credits 3,687
My method:
set Name%NN%=filename (NN is 1-99)

%random:~-2% gets the last two random digits, and then use those last two random digits to get %NameNN%

[ Last edited by zxcv on 2006-7-26 at 23:40 ]
Floor9 无奈何 Posted 2006-07-26 21:52
荣誉版主 Posts 356 Credits 1,338
A simple way to randomize the order is to add a %random% random number before each text line, then sort it with sort.
Try whether the following script meets the need. One feature of this script is that it does not generate temporary files.


  1. @echo off
  2. if "%1" NEQ "$" (
  3. for /f "tokens=1,2 delims=:" %%a in ('"%~0" $^|sort') do @echo %%b
  4. ) else for /f %%i in ('dir /b /a-d') do @call :sub %%i
  5. goto :EOF
  6. :sub
  7. echo %random%:%*
  8. goto :EOF
Posted by 无奈何 2006-07-26 21:43
Floor10 voiL Posted 2006-07-27 00:08
中级用户 Posts 189 Credits 384
Brother 无奈何, I tried the method you posted. The results are not much different from what I wrote before, and it can't achieve randomness in the true sense, because the result obtained after each run is the same every time.

Also, in front of the output filename there is always a group of "numbers" of varying length. I think the uneven length of these "numbers", together with the irregular filenames, may also be a problem for the later program.
Floor11 doscc Posted 2006-07-27 02:11
中级用户 Posts 93 Credits 256 From 广东
Improved code:
Added:
"automatically obtain the file count and set the random numbers according to the number of files"
"progress display"


[ Last edited by doscc on 2006-7-27 at 21:53 ]
Floor12 voiL Posted 2006-07-27 05:45
中级用户 Posts 189 Credits 384
After preliminary testing, doscc's code is indeed effective. The list generated each time is different.

Thanks, doscc.
Floor13 zh159 Posted 2006-07-27 15:07
金牌会员 Posts 1,467 Credits 3,687
doscc's efficiency is relatively low. The problem is here:
:ls
set num=%1
for /f "tokens=1,2* delims=:" %%a in ('type tem.txt') do if "%%a"=="%num%" echo %%b >> list.txt
goto :EOF

In this part, after %random% generates a random number, each random number has to "type tem.txt" once, and only when the line matching "%%a"=="%num%" is found does it write to List.txt; if the generated random number "%num%" is not within the range of "type tem.txt", then a random number has to be generated again.

I wrote a section that's faster:

@echo off
copy nul List.txt >NUL
setlocal EnableDelayedExpansion
for /f "delims=" %%a in ('dir/b/s *.mp3^|find ".mp3"') do ( search all folders under the current directory (can be omitted)
set Name=%%a
set /a N=!N! + 1
set Name!N!=!Name:%cd%=.!) replace the current directory generated by “dir/s” with “.”; if there is no “dir/s” it will be ignored automatically

echo.
echo Randomly generating the list, please wait...
:loop
set N=%random:~-3% for 100 files or more use 3, for less than 100 use 2 (the more digits, the slower it gets)
if "%N%" == "000" goto loop for 100 files or more use 000, for less than 100 use 00
if "%N:~0,1%" == "0" set N=%N:~1%
if "%N:~0,1%" == "0" set N=%N:~1%
if %N% GTR 137 goto loop change to the total number of files

set /a M=!M!+1
echo echo %%Name!N!%%^>^>List.txt>Temp.bat
call Temp.bat
if %M% GEQ 300 del Temp.bat & exit number of lines to generate in the list
goto loop


Set the name variables as NameN, use “if %N% GTR 137 goto loop“ to control %random% so that it generates the random number variable N within the file count range (“if "%N:~0,1%" == "0" set N=%N:~1%” removes the leading “0” from the random number), then write Name%N% to the list;

The following section automatically detects the file count and sets the parameters

@echo off
set DIR=dir/s “dir” searches only the current directory, “dir/s” searches all folders under the current directory
set 生成列表行数=200

for /f "tokens=1 delims= " %%i in ('%DIR% *.mp3^|find "个文件"') do set 文件数量=%%i
if %文件数量% GEQ 100 set X=3
if %文件数量% GEQ 100 set NN=000
if %文件数量% LSS 100 set X=2
if %文件数量% LSS 100 set NN=00
if %文件数量% LSS 10 set X=1
if %文件数量% LSS 10 set NN=0
copy nul List.txt >NUL
setlocal EnableDelayedExpansion
for /f "delims=" %%a in ('%DIR%/b *.mp3^|find ".mp3"') do (
set Name=%%a
set /a N=!N! + 1
set Name!N!=!Name:%cd%=.!)

echo.
echo Randomly generating the list, please wait...

echo :loop>Loop.bat
echo set N=%%random:~-%X%%%>>Loop.bat
echo if "%%N%%" == "%NN%" goto loop>>Loop.bat
echo if "%%N:~0,1%%" == "0" set N=%%N:~1%%>>Loop.bat
echo if "%%N:~0,1%%" == "0" set N=%%N:~1%%>>Loop.bat
echo if %%N%% GTR %文件数量% goto loop>>Loop.bat
:loop
call Loop.bat
set /a M=!M!+1
echo echo %%Name!N!%%^>^>List.txt>Temp.bat
call Temp.bat
if %M% GEQ %生成列表行数% goto :End
goto loop

:End
del Loop.bat
del Temp.bat
exit


[ Last edited by zxcv on 2006-7-27 at 15:58 ]
Floor14 namejm Posted 2006-07-27 17:54
荣誉版主 Posts 1,737 Credits 5,226 From 成都
  The code in post #11 has one defect: it cannot exclude duplicate filenames in the list.

  The following code can avoid this defect. The main idea is: first use for+findstr /n to calculate the number of mp3 files max in the folder to be operated on, then use %random% to generate a random three-digit number num (assuming the maximum number of files is 999); if num is greater than max, then generate num again; if num is less than or equal to max, and the filename on line num has not yet been added to list.txt, then write the filename numbered num into list.txt, and at the same time write this number into num.txt; if num appears in num.txt at this time, then recheck num...

  Because there is a large amount of text query processing, this code is relatively inefficient, so please be patient while it runs:


[ Last edited by namejm on 2006-7-28 at 09:00 ]
Floor15 doscc Posted 2006-07-27 20:38
中级用户 Posts 93 Credits 256 From 广东
To meet the OP's requirement, the code written will have relatively low efficiency.

My code should not produce duplicate lines.

Because the filtering is done in the following line

echo %y% | findstr /r "\<%r%\>" >NUL || set y=%y% %r% & call :ls %r%
y records each different random number

When r does not appear in y, then r is recorded and :ls is called to append line r from tem.txt into list.txt
1 2 3 4  Next
[ Contact the Union admin team - 中国DOS联盟 - Standard version ]
Sponsored by ifanr Inc | © 2001–2023