Syborg
Syborg

Reputation: 37

Batch File Playlist random sort

I have put together a small batch file program to create a playlist

@echo off
DIR /S /o:n /b *.avi > Playlist.m3u

Is there a way to change this so that it will sort in a random order each time it is run?

Upvotes: 2

Views: 1244

Answers (3)

Endoro
Endoro

Reputation: 37569

Solution without a TEMP file:

@echo off &setlocal
set "playlist=Playlist.m3u"
del %playlist% 2>nul
set /a files=0
for %%i in (*.avi) do set /a files+=1
if %files% equ 0 (echo No AVI found&goto:eof) else echo %files% AVI's found.
set /a cnt=%files%-1
for /l %%i in (0,1,%cnt%) do for /f "delims=" %%a in ('dir /b /a-d *.avi^|more +%%i') do if not defined $avi%%i set "$avi%%i=%%a"
:randomloop
set /a rd=%random%%%%files%
call set "avi=%%$avi%rd%%%"
if not defined avi goto :randomloop
set "$avi%rd%="
>>%playlist% echo %avi%
set /a cnt-=1
if %cnt% geq 0 goto:randomloop
echo Done!
endlocal

This doesn't use DelayedExpansion, so it can handle files with exclamation marks in its name. It takes a bit more time, but also doesn't need a temp file.

Upvotes: 1

Magoo
Magoo

Reputation: 80033

@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
::
:: establish a tempfile name
::
:temploop
SET tempfile="%temp%\temp%random%.tmp"
IF EXIST %tempfile% GOTO temploop
::
:: Write the list of filenames with each
:: prefixed by a random number and a colon
::
(FOR /f "delims=" %%i IN (
  'dir /s/b *.avi'
 ) DO ECHO !random!:%%i
)>%tempfile% 
::
:: Write the playlist.
:: sort the tempfile (which places it 
:: in random order) and remove the number:
::
(FOR /f "tokens=1*delims=:" %%i IN (
  ' sort ^<%tempfile% ') DO ECHO %%j
) >playlist.m3u
::
:: and delete the tempfile.
::
DEL %tempfile% 2>NUL

Should work - but it will have difficulties if your file/pathnames contain !

Documentation in the code.

Upvotes: 0

Nate Hekman
Nate Hekman

Reputation: 6657

It can be done, but it won't be pretty! Can you use a better platform instead of batch files? Maybe this is just the opportunity you've been waiting for to learn Powershell! :-)

However, if you insist on batch, here's the general approach I'd take if I were to try:

  1. Count the number of .avi files in your folder.
  2. Pick a random number between 0 and this number. For example, set /a randomLineNum=%random% %% 10 will set %randomLineNum% to a number from 0 to 9.
  3. Use something like for /f "skip=%randomLineNum%" %%L in ('dir /s /o:n /b *.avi') ... to grab that random line, and echo %%L > Playlist.m3u.
  4. Go back to #2.

That simplistic approach will end up with duplicates, and I didn't build in any way to exit the loop. I leave those problems for you to solve (or to ask in a future question). :-)

Upvotes: 1

Related Questions