|
voiL
中级用户
积分 384
发帖 189
注册 2005-10-19
状态 离线
|
『楼 主』:
一个关于随机获取文件名的问题.
运行环境:XP SP2 CMD.
这是一个朋友询问我的问题,觉得挺有趣,但由于水平有限,我又写不出来这样的批处理.
题目是这样的:
条件:获取的名字必须是随机的,不能太有规律(不能是完全按大小或名字或建立日期等),而且有数量限制(以100个文件为例).因为以大小或名字等排列方式,我自己就写出来了,难倒我的就是随机跟100个文件这里.
在MP3目录下,我有数目N的MP3文件(基本都是以中文命名的),现在我想用批处理随机生成一个M3U列表,然后调用WMP来播放,以实现WMP的随机播放.
其它的我都能写,就单单是随机获取文件名这个步骤我写不出来.
不知论坛上有没感兴趣的朋友,麻烦给出个代码.
[ Last edited by voiL on 2006-7-26 at 19:37 ]
|
|
2006-7-26 19:27 |
|
|
voiL
中级用户
积分 384
发帖 189
注册 2005-10-19
状态 离线
|
『第
2 楼』:
对了,如果BAT实现不了的话,可以考虑VBS,因为我对VBS不熟,没办法用VBS来写.
|
|
2006-7-26 19:38 |
|
|
namejm
荣誉版主
batch fan
积分 5226
发帖 1737
注册 2006-3-10 来自 成都
状态 离线
|
『第
3 楼』:
用%random%和findstr /n 估计能行,主要思路就是先用findstr /n 来给MP3文件名列表编号,然后用%random%来生成随机数,然后把%random%所代表的文件名列出来。细节问题,暂时还没有考虑到,具体的代码也还没有写出来,先写个思路在这里,看各位还有什么好的思路没有。
|
尺有所短,寸有所长,学好CMD没商量。
考虑问题复杂化,解决问题简洁化。 |
|
2006-7-26 19:40 |
|
|
voiL
中级用户
积分 384
发帖 189
注册 2005-10-19
状态 离线
|
『第
4 楼』:
呵呵,%random%这些参数太深奥了,还没完全弄懂,所以还没办法写出来,高手见笑了.
|
|
2006-7-26 20:48 |
|
|
zh159
金牌会员
积分 3687
发帖 1467
注册 2005-8-8
状态 离线
|
『第
5 楼』:
WMP、WINAMP不是有随机播放功能么?这样做有点罗嗦了吧^_^
|
|
2006-7-26 20:53 |
|
|
voiL
中级用户
积分 384
发帖 189
注册 2005-10-19
状态 离线
|
『第
6 楼』:
Quote: | Originally posted by zxcv at 2006-7-26 20:53:
WMP、WINAMP不是有随机播放功能么?这样做有点罗嗦了吧^_^ |
|
我感兴趣的并不是它是否能实现随机播放,而是怎么去实现随机获取文件名的办法而已.由于自己搞不定,没办法之下才来请教的.
|
|
2006-7-26 21:00 |
|
|
voiL
中级用户
积分 384
发帖 189
注册 2005-10-19
状态 离线
|
『第
7 楼』:
我曾经也想过通过名字、日期、大小来分别排列,然后各取前面的部分文件名来再进行名字方式排列的,但这方法只能用一次,因为每一次生成的名字还是一样的,不能实现随机取得文件名.
|
|
2006-7-26 21:01 |
|
|
zh159
金牌会员
积分 3687
发帖 1467
注册 2005-8-8
状态 离线
|
『第
8 楼』:
我的办法:
set Name%NN%=文件名(NN为1-99)
%random:~-2%获取后两位随机数,根据后两位随机数得到%NameNN%
[ Last edited by zxcv on 2006-7-26 at 23:40 ]
|
|
2006-7-26 21:08 |
|
|
无奈何
荣誉版主
积分 1338
发帖 356
注册 2005-7-15
状态 离线
|
『第
9 楼』:
随机排序的简单做法是在文本行前增加 %random% 随机数,然后 sort 排序一下。
试试下面的脚本是否满足需要,此脚本的特点是不产生临时文件。
Quote: |
- @echo off
- if "%1" NEQ "$" (
- for /f "tokens=1,2 delims=:" %%a in ('"%~0" $^|sort') do @echo %%b
- ) else for /f %%i in ('dir /b /a-d') do @call :sub %%i
- goto :EOF
- :sub
- echo %random%:%*
- goto :EOF
无奈何发表于 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
|
|
2006-7-26 21:52 |
|
|
voiL
中级用户
积分 384
发帖 189
注册 2005-10-19
状态 离线
|
『第
10 楼』:
无奈何兄,你给出的方法我试过,运行结果与我之前所写的也所差无几,不能实现真正意义上的随机,因为每一次运行后所得到的结果都是一样的.
而且在输出的文件名前面都会有一组长度不一的"编号",我想这些"编号"的长度不一与文件名的不规则,对于后面的程序来说也是个问题.
|
|
2006-7-27 00:08 |
|
|
doscc
中级用户
积分 256
发帖 93
注册 2006-3-26 来自 广东
状态 离线
|
『第
11 楼』:
改进后代码:
增加了:
"自动获得 文件数量 跟拒文件个数 设置随机数"
"进度显示"
@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 以完成 %n% %% ....)
goto :EOF [ Last edited by doscc on 2006-7-27 at 21:53 ]
|
|
2006-7-27 02:11 |
|
|
voiL
中级用户
积分 384
发帖 189
注册 2005-10-19
状态 离线
|
『第
12 楼』:
经初步测试,doscc兄的代码确实有效,每次生成的列表都不一样的.
谢谢doscc兄.
|
|
2006-7-27 05:45 |
|
|
zh159
金牌会员
积分 3687
发帖 1467
注册 2005-8-8
状态 离线
|
『第
13 楼』:
doscc 效率比较低,问题出在:
Quote: | :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 |
|
这段,%random%产生随机数后,每个随机数都要“type tem.txt”一次,搜索到"%%a"=="%num%"行才写入List.txt;如果生成的随机数“%num%”不在“type tem.txt”范围内,又得再生成随机数
我写了一段,速度快些:
Quote: | @echo off
copy nul List.txt >NUL
setlocal EnableDelayedExpansion
for /f "delims=" %%a in ('dir/b/s *.mp3^|find ".mp3"') do ( 搜索当前目录下所有文件夹(可不用)
set Name=%%a
set /a N=!N! + 1
set Name!N!=!Name:%cd%=.!) 将“dir/s”生成的当前目录替换为“.”,没有“dir/s”就会自动忽略
echo.
echo 随机生成列表,请稍等...
:loop
set N=%random:~-3% ≥100个以上文件为3,<100个以下为2(位数越高速度越慢)
if "%N%" == "000" goto loop ≥100个以上文件为000,<100个以下为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 改为文件总数量
set /a M=!M!+1
echo echo %%Name!N!%%^>^>List.txt>Temp.bat
call Temp.bat
if %M% GEQ 300 del Temp.bat & exit 生成列表的行数
goto loop |
|
将名称 set 变量为 NameN,用”if %N% GTR 137 goto loop“控制%random%在文件数量范围内生成随机数变量N(“if "%N:~0,1%" == "0" set N=%N:~1%”去处随机数前面的“0”),用Name%N%写入列表;
以下一段自动检测文件数量设置参数
Quote: | @echo off
set DIR=dir/s “dir”为只搜索当前目录,“dir/s”为搜索当前目录下所有文件夹
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 随机生成列表,请稍等...
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 ]
|
|
2006-7-27 15:07 |
|
|
namejm
荣誉版主
batch fan
积分 5226
发帖 1737
注册 2006-3-10 来自 成都
状态 离线
|
『第
14 楼』:
11楼的代码存在一个缺憾:在列表中不能排除重复的文件名。
以下代码可以避免这一缺憾,主要思想是:先用for+findstr /n来计算要操作的文件夹下mp3文件的个数max,然后用%random%生成随机的三位数num(假设文件的最大个数为999个);如果num大于max,则重新生成随机数num;如果num小于或等于max,且第num行的文件名还没有加入list.txt,则把编号为num的文件名写入list.txt,同时把此编号写入num.txt;如果此时num在num.txt中出现,则重新检测num……
因为有大量的文本查询过程,此代码的效率比较低,执行的时候请耐心等待:
@echo off
if exist list.txt del /q list.txt
if exist num.txt del /q num.txt
echo 已经列表的曲目编号:>num.txt
set _time=1
for /f "tokens=1 delims=:" %%i in ('dir /a-d /b "要操作的文件夹\*.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 "要操作的文件夹\*.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没商量。
考虑问题复杂化,解决问题简洁化。 |
|
2006-7-27 17:54 |
|
|
doscc
中级用户
积分 256
发帖 93
注册 2006-3-26 来自 广东
状态 离线
|
『第
15 楼』:
实现楼主的要求 写出来的代码效率是比较底的
我的代码 应该不会出现重复的行
因为在下面这一行做了过虑
echo %y% | findstr /r "\<%r%\>" >NUL || set y=%y% %r% & call :ls %r%
y 记录每个不一样的 随机数
当 r 不在 y 中出现时 就 记录 r 并 调用 :ls 把 tem.txt 中的第 r 行 追加到 list.txt 里
|
|
2006-7-27 20:38 |
|