Reputation: 95
The purpose is to select a single folder at random from within a given text file containing a folder list using a batch script in Windows.
Step by step method:
SKIP
variable to a random number up to the number of lines in that text file
EVERYTHING WORKS UP TO THIS POINT%SKIP%
number of lines. Then do set VARNAME=%%I from the for loop. Then goto NextLine so it's not repeated until the end of the text file.
***THIS STEP GIVES ME ERROR: System cannot find file specified.[EDIT] On further testing, error only happens IF %SKIP% > 4 i.e. if SKIP corresponds to a line with a filepath on it, it gives that error. Else it works fine.
I've read all the answers everywhere, but can't solve it! If I take the for outside into a test file with just random words it works fine. So I can only presume it's something to do with the special characters in the dir output list that are causing problems? Any help much appreciated!
My Code:
:: Make the code run quietly
@ECHO OFF
:: Get home directory
set HOMEDIR=D:\External\My Pictures
:: Switch to the drive of HOMEDIR
:: If the drive letter of the current directory differs from HOMEDIR
:: Then change drive letter
:: Else change directory to root of that drive
:: Thanks Jatrim for if not http://stackoverflow.com/questions/1421441/batch-not-equal-operator
if not %cd:~0,2% == %HOMEDIR:~0,2% %HOMEDIR:~0,2% else cd %HOMEDIR:~0,2%
:: Change directory to HOMEDIR
cd "%HOMEDIR%"
:: Write a list of the subdirectories of HOMEDIR to file homedir.txt
dir "%cd%" /a:d >> homedir.txt
:: Calculate how many lines there are in homedir.txt
:: Thanks Aacini from http://stackoverflow.com/questions/13343144/random-line-of-text-ussing-batch
for /F "" %%I in (homedir.txt) do set /a LINES=%%I
echo LINES=%LINES%
:: enable delayed expansion (needed???)
setlocal EnableDelayedExpansion
:: Set a random integer (within the limit of variable LINES)
:: Thanks Aacini from http://stackoverflow.com/questions/13343144/random-line-of-text-ussing-batch
set /a SKIP=%random%%%LINES%
echo SKIP=%SKIP%
:: In homedir.txt the first 5 lines aren't directories
:: SKIP THESE LINES SOMEHOW
:: Thanks Andriy M for the inspiration! http://stackoverflow.com/questions/6409869/echo-the-nth-line-from-a-text-file-where-n-is-a-command-line-argument
:: If it's the same as SKIP, read line's contents into variable SCRDIR
for /F "usebackq delims= skip=%SKIP%" %%I in (homedir.txt) do (if not defined SCRDIRORIG set SCRDIRORIG=%%I & GoTo :NextLine)
pause
:NextLine
echo %SCRDIRORIG%
pause
Upvotes: 0
Views: 2741
Reputation: 70971
For a version without temporary files you can try with
@echo off
setlocal enableextensions disabledelayedexpansion
set "HOMEDIR=D:\External\My Pictures"
for /f "tokens=1,*" %%a in ('
cmd /q /v /c"for /d %%a in ("!HOMEDIR!\*") do (set /a "1000000000+(!random! * %random% %% (!random!+1^)^)" & echo( %%a)"
^| sort
^| cmd /q /v /c"(set /p "line^=" & echo(!line!)"
') do set "SCRDIRORIG=%%b"
echo Folder selected : %SCRDIRORIG%
The code creates a cmd
instance that will list all the folders under the indicated starting point prefixed with a random number. This list is sorted and then the first line in the list retrieved.
All this is wrapped inside a for /f
command so at the end we can separate the starting random number from the folder name and set the variable.
Upvotes: 0
Reputation: 4209
I've tried to carefully select the means for each step in the following code in order to avoid pitfalls.
HOMEDIR
is not strictly necessary here it is best done with a cd /d
which changes the drive as well if necessary. dir /b /ad
does not include '.' and '..' nor any junctions like dir /ad
would. find /c
combined with a negated search for the empty string yields the count directly without need for complicated extraction (or loops). nlines
is 0. So the alternative method is used. The quotient %RANDOM% / 32768
is in the desired range [0..1) so we only need to multiply it with nlines
. FOR
loop will choke on the skip=
option. FOR
loop extracts the desired line and stops immediately with a GOTO
. Not nice but effective. Here is the code:
@echo off &setlocal enableextensions
set "HOMEDIR=D:\External\My Pictures"
cd /d %HOMEDIR%
:: count the dirs
for /f %%I in ('dir /b /ad "%HOMEDIR%"^| find /c /v ""') do set "nlines=%%I"
:: pick a number from 0..nlines-1
set /A nskip=%random% * %nlines% / 32768
:: discard "skip=" option if no lines to skip
set skipopt=
if %nskip% GTR 0 set skipopt=skip=%nskip%
:: read line[nskip+1] from input and quit
for /F "%skipopt% delims=" %%I in ('dir /b /ad %HOMEDIR%') do set "LINE=%%I" & GOTO :out
:out
echo folder selected : %LINE%
Upvotes: 0
Reputation: 37589
I would recommend this:
@echo off &setlocal disabledelayedexpansion
for /f "tokens=1*delims=:" %%a in ('findstr /n $ homedir.txt') do (
set ".%%~a.=%%~b"
set /a DirCount=%%~a
)
set /a DirCount-=5
set /a Sample=%random%%%DirCount
set /a Sample+=5
for /f "tokens=1*delims==" %%a in ('set ".%Sample%."') do echo %%~b
Upvotes: 2