中国DOS联盟论坛

中国DOS联盟

-- 联合DOS 推动DOS 发展DOS --

联盟域名:www.cn-dos.net  论坛域名:www.cn-dos.net/forum
DOS,代表着自由开放与发展,我们努力起来,学习FreeDOS和Linux的自由开放与GNU精神,共同创造和发展美好的自由与GNU GPL世界吧!

游客:  注册 | 登录 | 命令行 | 会员 | 搜索 | 上传 | 帮助 »
中国DOS联盟论坛 » DOS批处理 & 脚本技术(批处理室) » 一个关于随机获取文件名的问题.
« [1] [2] [3] [4] »
作者:
标题: 一个关于随机获取文件名的问题. 上一主题 | 下一主题
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:

  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
        无奈何发表于    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
查看资料  发送邮件  发短消息 网志  OICQ (105400208)  编辑帖子  回复  引用回复
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
查看资料  发短消息 网志   编辑帖子  回复  引用回复
« [1] [2] [3] [4] »
请注意:您目前尚未注册或登录,请您注册登录以使用论坛的各项功能,例如发表和回复帖子等。


可打印版本 | 推荐给朋友 | 订阅主题 | 收藏主题



论坛跳转: