China DOS Union

-- Unite DOS · Advance DOS · Grow DOS --

Union site: www.cn-dos.net Forum site: www.cn-dos.net/forum
DOS stands for freedom, openness and progress. Let us work hard, learn from the openness and GNU spirit of FreeDOS and Linux, and together build and grow a free GNU GPL world!

中国DOS联盟论坛
The time now is 2026-06-22 07:21
中国DOS联盟论坛 » DOS批处理 & 脚本技术(批处理室) » A question about randomly obtaining file names. DigestI View 17,412 Replies 54
Original Poster Posted 2006-07-26 19:27 ·  中国 广东 肇庆 电信
中级用户
★★
Credits 384
Posts 189
Joined 2005-10-19 13:12
20-year member
UID 43709
Gender Male
Status Offline
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 ]
Floor 2 Posted 2006-07-26 19:38 ·  中国 广东 肇庆 电信
中级用户
★★
Credits 384
Posts 189
Joined 2005-10-19 13:12
20-year member
UID 43709
Gender Male
Status Offline
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.
Floor 3 Posted 2006-07-26 19:40 ·  中国 四川 成都 鹏博士宽带
荣誉版主
★★★★
batch fan
Credits 5,226
Posts 1,737
Joined 2006-03-10 00:38
20-year member
UID 51697
From 成都
Status Offline
  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.
尺有所短,寸有所长,学好CMD没商量。
考虑问题复杂化,解决问题简洁化。
Floor 4 Posted 2006-07-26 20:48 ·  中国 广东 肇庆 电信
中级用户
★★
Credits 384
Posts 189
Joined 2005-10-19 13:12
20-year member
UID 43709
Gender Male
Status Offline
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.
Floor 5 Posted 2006-07-26 20:53 ·  中国 广西 玉林 博白县 电信
金牌会员
★★★★
Credits 3,687
Posts 1,467
Joined 2005-08-08 12:00
20-year member
UID 44210
Status Offline
Doesn't WMP or WINAMP already have a random play function? Doing it this way is a bit too roundabout, isn't it? ^_^
Floor 6 Posted 2006-07-26 21:00 ·  中国 广东 肇庆 电信
中级用户
★★
Credits 384
Posts 189
Joined 2005-10-19 13:12
20-year member
UID 43709
Gender Male
Status Offline
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.
Floor 7 Posted 2006-07-26 21:01 ·  中国 广东 肇庆 电信
中级用户
★★
Credits 384
Posts 189
Joined 2005-10-19 13:12
20-year member
UID 43709
Gender Male
Status Offline
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.
Floor 8 Posted 2006-07-26 21:08 ·  中国 广西 玉林 博白县 电信
金牌会员
★★★★
Credits 3,687
Posts 1,467
Joined 2005-08-08 12:00
20-year member
UID 44210
Status Offline
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 ]
Floor 9 Posted 2006-07-26 21:52 ·  中国 辽宁 锦州 中移铁通
荣誉版主
★★★
Credits 1,338
Posts 356
Joined 2005-07-15 12:09
20-year member
UID 40733
Gender Male
Status Offline
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
  ☆开始\运行 (WIN+R)☆
%ComSpec% /cset,=何奈无── 。何奈可无是原,事奈无做人奈无&for,/l,%i,in,(22,-1,0)do,@call,set/p= %,:~%i,1%<nul&ping/n 1 127.1>nul

Floor 10 Posted 2006-07-27 00:08 ·  中国 广东 中山 广东瑞江科技有限公司BGP数据中心
中级用户
★★
Credits 384
Posts 189
Joined 2005-10-19 13:12
20-year member
UID 43709
Gender Male
Status Offline
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.
Floor 11 Posted 2006-07-27 02:11 ·  中国 北京 海淀区 IDC机房
中级用户
★★
Credits 256
Posts 93
Joined 2006-03-26 22:12
20-year member
UID 52853
Gender Male
From 广东
Status Offline
Improved code:
Added:
"automatically obtain the file count and set the random numbers according to the number of files"
"progress display"

@echo off
dir /b *.mp3 | findstr /n "." >tem.txt
for /f "tokens=1 delims=:" %%g in (tem.txt) do set maxnum=%%g
copy nul list.txt >NUL
set "y="
set "n="

:s
set r=%random:~-1%%random:~-1%%random:~-1%
set /a r*=1
if "%r%" GTR "%maxnum%" goto s
for /f "tokens=1 delims=:" %%i in ('type list.txt ^| findstr /n "."') do if "%%i"=="100" del tem.txt & exit
echo %y% | findstr /r "\<%r%\>" >NUL || set y=%y% %r% & call :ls %r%

goto s

:ls
set num=%1
for /f "tokens=1,2* delims=:" %%a in (tem.txt) do (if "%%a"=="%num%" echo %%b >> list.txt && set /a n+=1 & title Completed %n% %% ....)
goto :EOF


[ Last edited by doscc on 2006-7-27 at 21:53 ]
Floor 12 Posted 2006-07-27 05:45 ·  中国 广东 中山 广东瑞江科技有限公司BGP数据中心
中级用户
★★
Credits 384
Posts 189
Joined 2005-10-19 13:12
20-year member
UID 43709
Gender Male
Status Offline
After preliminary testing, doscc's code is indeed effective. The list generated each time is different.

Thanks, doscc.
Floor 13 Posted 2006-07-27 15:07 ·  中国 广西 玉林 博白县 电信
金牌会员
★★★★
Credits 3,687
Posts 1,467
Joined 2005-08-08 12:00
20-year member
UID 44210
Status Offline
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 ]
Floor 14 Posted 2006-07-27 17:54 ·  中国 四川 成都 鹏博士宽带
荣誉版主
★★★★
batch fan
Credits 5,226
Posts 1,737
Joined 2006-03-10 00:38
20-year member
UID 51697
From 成都
Status Offline
  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:

@echo off
if exist list.txt del /q list.txt
if exist num.txt del /q num.txt
echo Number of tracks already listed:>num.txt
set _time=1
for /f "tokens=1 delims=:" %%i in ('dir /a-d /b "folder to operate on\*.mp3"^|findstr /n .') do set max=%%i
:loop
set num=%random:~-3%
set /a num=1%num%-1000
if %num% leq 0 goto loop
if %num% gtr %max% goto loop
for /f %%i in (num.txt) do if %%i equ %num% goto loop
for /f "tokens=1,2* delims=:" %%i in ('dir /a-d /b "folder to operate on\*.mp3"^|findstr /n .') do (
if %%i equ %num% (
echo %%i>>num.txt & echo %%j>>list.txt && set /a _time+=1 && if %_time% lss %max% goto loop
)
)
del /q num.txt
start list.txt


[ Last edited by namejm on 2006-7-28 at 09:00 ]
尺有所短,寸有所长,学好CMD没商量。
考虑问题复杂化,解决问题简洁化。
Floor 15 Posted 2006-07-27 20:38 ·  中国 北京 海淀区 IDC机房
中级用户
★★
Credits 256
Posts 93
Joined 2006-03-26 22:12
20-year member
UID 52853
Gender Male
From 广东
Status Offline
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
Forum Jump: