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 05:58
中国DOS联盟论坛 » DOS批处理 & 脚本技术(批处理室) » A question about randomly obtaining file names. DigestI View 17,410 Replies 54
Floor 31 Posted 2006-07-28 09:48 ·  中国 广西 玉林 博白县 电信
金牌会员
★★★★
Credits 3,687
Posts 1,467
Joined 2005-08-08 12:00
20-year member
UID 44210
Status Offline
As for the "numbering" issue in Moderator 无奈何's code that voiL mentioned in post #10, I guess voiL appended >>List.txt after the line “echo %random%:%*”, whereas it should have been appended after “@echo %%b”
See post #25
Floor 32 Posted 2006-07-28 10:01 ·  中国 广东 云浮 电信
荣誉版主
★★★
Credits 718
Posts 313
Joined 2005-09-26 00:00
20-year member
UID 42844
Gender Male
Status Offline
To obtain the total number of mp3 files in the directory, use for /r %%i in (*.mp3) do set /a n+=1 to replace:

[1] for /f "tokens=1 delims= " %%i in ('dir *.mp3^|find "个文件"') do set 文件数量=%%i

[2] dir /b *.mp3 | findstr /n "." >tem.txt
for /f "tokens=1 delims=:" %%g in (tem.txt) do set maxnum=%%g

[3] for /f "delims=" %%i in ('dir /b /a-d') do @call :sub %%i

Would that be a bit more efficient? Please have willssort do a deeper analysis.
Floor 33 Posted 2006-07-28 10:32 ·  中国 四川 成都 鹏博士宽带
荣誉版主
★★★★
batch fan
Credits 5,226
Posts 1,737
Joined 2006-03-10 00:38
20-year member
UID 51697
From 成都
Status Offline
Originally posted by zxcv at 2006-7-28 09:42:

Honestly, I added those when posting to explain what each line does. They were never in the real BAT to begin with (which is why I said: don't include the red parts); but you should be able to tell whi...


  If you're only adding comments, you can use the format :: comment content or rem comment content on the line above or below the statement.

[ Last edited by namejm on 2006-7-28 at 10:35 ]
尺有所短,寸有所长,学好CMD没商量。
考虑问题复杂化,解决问题简洁化。
Floor 34 Posted 2006-07-28 14:16 ·  中国 四川 成都 鹏博士宽带
荣誉版主
★★★★
batch fan
Credits 5,226
Posts 1,737
Joined 2006-03-10 00:38
20-year member
UID 51697
From 成都
Status Offline
  I discussed Moderator 无奈何's code in post #25 with bagpipe, and found that this section of code can still be simplified further, so I'm posting bagpipe's simplified version:

1、

@echo off
setlocal enabledelayedexpansion
copy nul List.txt >NUL
if "%1" NEQ "$" (
for /f "tokens=1,2 delims=:" %%a in ('"%~0" $^|sort') do echo %%b>>List.txt
) else for /f "delims=" %%i in ('dir /b /a-d *.mp3') do echo !random!:%%i


2、

@echo off
copy nul List.txt >NUL
if "%1" NEQ "$" (
for /f "tokens=1,2 delims=:" %%a in ('"%~0" $^|sort') do echo %%b>>List.txt
) else for /f "delims=" %%i in ('dir /b /a-d *.mp3') do call echo %%random%%:%%%%i
尺有所短,寸有所长,学好CMD没商量。
考虑问题复杂化,解决问题简洁化。
Floor 35 Posted 2006-07-28 16:13 ·  中国 广东 广州 中移铁通
中级用户
★★
Credits 256
Posts 93
Joined 2006-03-26 22:12
20-year member
UID 52853
Gender Male
From 广东
Status Offline
Originally posted by 无奈何 at 2006-7-27 23:51:
@echo off

if "%1" NEQ "$" (

for /f "tokens=1,2 delims=:" %%a in ('"%~0" $^|sort') do @echo %%b

) else for /f "delims=" %%i in ('dir /b /a-d') do @call :sub %%i

goto :EOF

:sub

echo %random%:%*

goto :EOF


Brother 无奈何's code is really brilliant! Worthy of a moderator indeed!

The clever part is ('"%~0" $^|sort') and echo %random%:%* perfectly matching front and back!

A simple explanation of the code:
Get all the files, mark each file with a random number in front, then sort, filter, and output!

[ Last edited by doscc on 2006-7-28 at 16:18 ]
Floor 36 Posted 2006-07-28 16:22 ·  中国 广东 广州 中移铁通
中级用户
★★
Credits 256
Posts 93
Joined 2006-03-26 22:12
20-year member
UID 52853
Gender Male
From 广东
Status Offline
Re: namejm & bagpipe
The line call echo %%random%%:%%%%i is used very nicely!
Floor 37 Posted 2006-07-28 19:49 ·  中国 山西 运城 中移铁通
元老会员
★★★★
Batchinger
Credits 4,432
Posts 1,512
Joined 2002-10-18 00:00
23-year member
UID 19
Gender Male
Status Offline
Originally posted by 220110 at 2006-7-28 10:01:
To obtain the total number of mp3 files in the directory, use for /r %%i in (*.mp3) do set /a n+=1 to replace:

for /f "tokens=1 delims= " %%i in ('dir *.mp3^|find "个文件"') do set 文件数量=%%i

dir /b *.mp3 | findstr /n "." >tem.txt
for /f "tokens=1 delims=:" %%g in (tem.txt) do set maxnum=%%g

for /f "delims=" %%i in ('dir /b /a-d') do @call :sub %%i

Would that be a bit more efficient? Please have willssort do a deeper analysis.

Re 220110 'post #32':

Regarding the code snippets above, I have the following shallow opinions:

1. From the algorithmic point of view, the time complexity of each code segment is the same, so their actual running efficiency mainly depends on details in system support;

2. From the code point of view, the efficiency advantage of your code lies in not using text input/output operations; and as everyone knows, I/O has always been one of the bottlenecks affecting code efficiency, something the other snippets cannot match. Among the other code snippets, code should be more efficient than code , because code not only edits the text output of dir (adding line numbers), but also the amount of text processed by for/f is clearly larger than in code ; as for the use of code , because it involves recursive calls in batch files (essentially data reading), its efficiency is also lower than code .

3. But in actual testing, the results were not completely as analyzed in point 2. In small-scale tests (the Audio directory, 746 files), your code had the highest efficiency (140ms), and surprisingly the next was not code (234ms), but code (218ms). Analyzing the result, the reason is that code does not directly use for/f to analyze the output of findstr, but instead uses a temporary file temp.txt. To improve file I/O efficiency, the operating system opens corresponding file I/O buffers in memory to improve file access speed, while code cannot “enjoy this preferential policy,” causing it to lag behind in the early stage of the race. This is a typical example of code efficiency being affected by system characteristics.

4. In some large-scale tests (whole-disk test, file count >60000), the situation changed again. The result of the first test was: your code > code > code , but in subsequent tests the situation became code > your code > code . The reason is that the operating system has designed a hard-disk-based Prefetch mechanism for large-scale file I/O actions such as dir. Since your code cannot “benefit from it,” it fell flat after a good start. Code , on the other hand, exposed the weakness of its file-processing algorithm as the scale increased. This is another fairly typical example of code efficiency being affected by system characteristics.

5. From a practical point of view, because for does not traverse hidden and system attribute files, your code will produce deviations in some complex application scenarios. In code , because of the lack of the /a-d switch, directories will also be counted as files. In addition, if /w is added to the dir switches in code , it helps somewhat with efficiency, and adding the /-c switch removes the comma separators in the result. And if code is changed to use the temporary-file mechanism of code , efficiency can be further improved. So, taking all the plans together, my revised plan is as follows:


@echo off & setlocal
dir %1 /a/s/w/-c | findstr "个文件">temp.txt
for /f %%i in (temp.txt) do set filenum=%%i
echo.FileNum:%filenum%
if exist temp.txt del temp.txt


[ Last edited by willsort on 2006-7-29 at 01:27 ]
※ Batchinger 致 Bat Fans:请访问 批处理编程的异类 ,欢迎交流与共享批处理编程心得!
Floor 38 Posted 2006-07-29 00:23 ·  中国 广东 云浮 电信
荣誉版主
★★★
Credits 718
Posts 313
Joined 2005-09-26 00:00
20-year member
UID 42844
Gender Male
Status Offline
Re willsort:
I wonder whether you tested the case of deep multi-level subdirectories?
I always feel that for /r is more efficient than dir /b /a:-d, leaving aside the system attribute issue you mentioned in point 5.
I only tested it on the system drive from the root directory. The system drive should count as having enough files and deep enough paths, right?
For now I don't have any other new test methods or environments to compare with.

Re namejm & bagpipe:
You two really are good! Still able to simplify it.
It's just that you ignored 无奈何's original intention—not to use temporary files.
Let's see how much more you can simplify it without using temporary files!! Just a little goading, haha

[ Last edited by 220110 on 2006-7-29 at 00:25 ]
Floor 39 Posted 2006-07-29 01:46 ·  中国 山西 太原 中移铁通
元老会员
★★★★
Batchinger
Credits 4,432
Posts 1,512
Joined 2002-10-18 00:00
23-year member
UID 19
Gender Male
Status Offline
Re 220110:

Before you replied, I had already started re-editing the original draft, and only afterward did I see your reply, in which the new issue you mentioned is touched on slightly.

As for the simplification of Brother 无奈何's code by Brothers namejm & bagpipe, it actually does not involve temporary files. The list.txt in the code is in fact a file for saving result data, while Brother 无奈何's original solution output them directly to the console.

And Brother 无奈何's if/lse structure, which Brother namejm found hard to understand, is in fact the real key to avoiding temporary files. In other words, if temporary files are used, then the if/lse structure need not be used, such as in the following code that I edited.

Also, the most outstanding feature of Brother 无奈何's code lies not in its conciseness or obscurity, but in its efficient algorithm of going against the usual approach: instead of controlling the generation of random numbers, it controls the generation of the list. That is something the other code snippets cannot compare with.


@echo off
cd.>temp.txt & cd.>list.txt
for /f "delims=" %%i in ('dir *.mp3 /b/a-d') do call echo %%random%%%%random%%:%%i>>temp.txt
sort < temp.txt > temp1.txt
for /f "tokens=1,2 delims=:" %%a in (temp1.txt) do echo %%b>>list.txt
for %%f in (temp?.txt) do del %%f


[ Last edited by willsort on 2006-7-29 at 01:48 ]
※ Batchinger 致 Bat Fans:请访问 批处理编程的异类 ,欢迎交流与共享批处理编程心得!
Floor 40 Posted 2006-07-29 20:44 ·  中国 四川 成都 鹏博士宽带
荣誉版主
★★★★
batch fan
Credits 5,226
Posts 1,737
Joined 2006-03-10 00:38
20-year member
UID 51697
From 成都
Status Offline
  After looking at Moderator willsort's code in post #39, I finally learned that an empty text file can also be created with a method like cd.>, which was eye-opening.

  Moderator 无奈何's code really is very clever. It sets aside the conventional idea of printing line numbers in order first and then selecting them in random order, and instead directly assigns line numbers in random order and then reorders them, seeking order in chaos to achieve a randomized arrangement. The efficiency of this method is not even on the same order of magnitude as that of conventional solutions. However, because it calls itself, if the opening line @echo off is removed, incorrect results will be obtained. Therefore this code can only be used as an independent script, and cannot be called as an internal sub-section within some other script. If it could be made into a sub-section that can be called in a loop, it would be perfect.

  While I'm at it, let me ask a question: I'm not very familiar with using the redirection symbols < and > consecutively in the same statement. Can someone explain it a bit? Mainly the usage scenarios and whether there are any restrictions or conditions.
尺有所短,寸有所长,学好CMD没商量。
考虑问题复杂化,解决问题简洁化。
Floor 41 Posted 2006-07-29 22:17 ·  中国 辽宁 锦州 中移铁通
荣誉版主
★★★
Credits 1,338
Posts 356
Joined 2005-07-15 12:09
20-year member
UID 40733
Gender Male
Status Offline
Brother willsort's summary really gets right to the point.
To be honest, I didn't pay too much attention to efficiency issues in the code I posted; I just didn't want to generate temporary files. This piece of code is only a typical example of recursive calling. The discussion has already explained it quite clearly, so I won't say more. If temporary files are not a concern, then the code Brother willsort posted in post #39 is undoubtedly the simplest and easiest to control.
As for the simplification by Brother namejm and Brother bagpipe, I really like this spirit. It can improve the quality of the code, improve coding skill, and sometimes even lead to new discoveries. Of course, this also involves code-writing habits. For example, unless absolutely necessary, I try to avoid using delayed environment variables, and prefer calling external code sections instead. The program structure looks a bit nicer that way. I haven't researched the efficiency issue very deeply yet. Also, in Brother namejm's post #34, code snippet 2, the line %%random%%:%%%%i has a problem: when there are files like 1.mp3 and 2.mp3, the filenames will be lost. The reason is that parameter i is escaped multiple times. The fix is to remove two %; see the code in #39.
  ☆开始\运行 (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 42 Posted 2006-12-10 03:13 ·  中国 广东 东莞 电信
银牌会员
★★★
Credits 1,179
Posts 442
Joined 2006-09-09 22:47
19-year member
UID 62249
Status Offline
Brother willsort's code is indeed concise and excellent, but there is one problem. If you want to obtain files from all subdirectories under a certain drive, then there's a problem: the output contains only the drive letter.
Floor 43 Posted 2006-12-10 14:29 ·  中国 广西 玉林 博白县 电信
金牌会员
★★★★
Credits 3,687
Posts 1,467
Joined 2005-08-08 12:00
20-year member
UID 44210
Status Offline
Adding my latest one to this thread too ^_^

@echo off
for /f "delims=" %%i in ('dir/a-d/b *.mp3') do call set $%%random%%$%%i=$
for /f "tokens=1,2* delims=$=" %%i in ('set $') do echo %%j
pause
Floor 44 Posted 2006-12-10 14:57 ·  中国 湖北 荆门 电信
荣誉版主
★★★
Credits 2,013
Posts 718
Joined 2006-02-18 07:07
20-year member
UID 50550
Status Offline
Using sort /+n can also achieve a random list to a certain extent.
@echo off
set /a num=%random% %% 4 + 1
dir /b /a-d | sort /+%num%
pause
exit /b 0

It requires the filenames not to be too similar.
Floor 45 Posted 2006-12-10 16:05 ·  中国 江西 南昌 电信
银牌会员
★★★
天的白色影子
Credits 2,343
Posts 636
Joined 2004-03-06 00:00
22-year member
UID 19350
Gender Male
Status Offline
You could consider repeatedly using sort with different %num% values to increase the randomness.
Forum Jump: