I'm an artist who is learning programming and I wanted to create a batch file that will select a random picture file from my references folder. The goal being to get a random picture to work on and study. I've looked around and the replies I see are hard to understand and are often linked with other features and functions I don't need. Simply put, how do I make a batch file that opens a random picture file from a folder (and subfolders)? Do I need to index every picture and then have a selector from that or can I just use %random% to open it?
Thank you for your help.
This is the basic batch file structure you'll need:
#Echo Off
Set "SrcDir=C:\Users\Jiosen\references"
Set "ExtLst=*.jpeg *.png *.tiff"
Set "i=0"
For /F "Delims=" %%A In ('Where /R "%SrcDir%" %ExtLst%') Do (Set /A i+=1
Call Set "$[%%i%%]=%%A")
Set /A #=(%Random%%%i)+1
Call Start "" "%%$[%#%]%%"
You may need to adjust lines 2 and 3 as necessary, (but do not remove or add any doublequotes).
PowerShell is more efficient in selecting files in a tree and getting a random file so why not use it from the batch.
Taking Compos batch as a template:
:: Q:\Test\2018\07\24\SO_51487674.cmd
#Echo Off
PushD "C:\Users\Jiosen\references"
Set "ExtLst=*.jpg,*.jpeg,*.png,*.tiff"
For /F "Delims=" %%A In ('
powershell -Nop -C "(Get-ChildItem * -R -File -Incl %ExtLst%|Get-Random).FullName"
') Do Start "" "%%A"
Get-ChildItem parameters -File,?-Include and Get-Random require at least PowerShell Version 3.0
According to the table in this link you need to upgrade Window 7 PowerShell v2 to at least V3, Windows 8 or higher should run the script without problem.
But I'd recommend to upgrade to 5.1 and possibly install PowerShell 6.0 (core) in parallel.
#SETLOCAL ENABLEDELAYEDEXPANSION
rem #CD C:\newfolder
#set count=0
#For /f "delims=" %%A in ('dir C:\users\*.* /ad /s /b') Do (
# set /a count=!count!+1
#rem If !Count! gtr 1 echo Num of folders
)
#Set /a num=%random% %% %Count% + 1
Echo %num% / %count%
For /f "skip=%num% delims=" %%A in ('dir C:\users\*.* /ad /s /b') Do (
Echo this is nth random folder
Echo Copy "%~dpnx0" "%%A"
rem Exit /b
)
pause
%Random% gives us a random number from 0 to 32K. #Set /a num=%random% %% %Count% + 1 uses modulo division (ie the remainder from a division) of 32K divided by how many will give us a random number in the range 0 to count. Then add 1 to make it 1 to count +1 (the number of folders). Then skip=%num% skips the first how ever many folders, reads the next, then exits the loop.
This is limited to 32K folders. See Dir /? for how to list files and files in subfolders. Every command above plus /? for help. See http://stackoverflow.com/questions/41030190/command-to-run-a-bat-file/41049135#41049135 for a CMD cheat sheet.
Related
I'm trying to group files arranged in some order so that I can zip them. I have m*n files in my folder and wish to move n files to m folders such that they're arranged in alphabetical order (or date created order, whichever is doable). So for files {A,B,C,D,E,F} I wish to create two new folders 1 and 2 such that 1 contains {A,B,C} and 2 contains {D,E,F}. If there's code to do the same thing on a mac, that would be great too, but I'm primarily looking to do this on windows.
I found a similar question, however I'm not able to create new folders within the loop or move the files to them.
#echo off
set /a "filesPerChunk=3, idx=0"
set /a fcount=1
for /F "delims=" %%I in ('dir /a-d /b') do (
echo Processing %%I
set /a "idx=idx+1"
set /a "mod=idx %% filesPerChunk"
if !mod! equ 0 (
md File-%fcount%
echo --- END OF CHUNK %fcount% ---
pause
)
move I File-%fcount%
if !mod! equ %filesPerChunk%-1(
set /a fcount+=1
)
)
I was trying to extract values from fcount to make new folders, but as I mentioned, I don't have a lot of experience writing batch scripts so I don't know if this even makes sense.
EDIT: So I had to move a few commands here and there because I realized I wouldn't be able to move the files if I had just the final check when creating the file, but I'm not sure if it works
I took the freedom to slightly simplify your logic:
#echo off
setlocal enabledelayedexpansion
set "filesPerChunk=3"
set "fcount=0"
set idx=0
for /F "delims=" %%I in ('dir /a-d /b') do (
REM echo Processing %%I
set /a idx=idx %% filesperchunk +1
if !idx! equ 1 set /a fcount+=1
ECHO md File-!fcount! 2>nul
ECHO move "%%I" "File-!fcount!\"
REM pause
)
After verifying it does what you want, remove both ECHO commands to actually enable the md and move commands.
Note: you can choose the sort order of your files with the /o switch. See dir /? for details.
I would like to keep the X latest files from a folder and delete the rest. Is this possible with FORFILES? If it's not I can fallback to another solution I seen here. Thanks for help.
I did this but it takes by dates: EDIT
forfiles /p [path] /s /d -5 /c "cmd /c echo #file"
(echo file for testing purpose)
#ECHO OFF
SETLOCAL
SET "targetdir=U:\destdir"
SET /a retain=10
FOR /f "skip=%retain%delims=" %%a IN (
'dir /b /a-d /o-d "%targetdir%\*" '
) DO ECHO (DEL "%targetdir%\%%a"
GOTO :EOF
You would need to change the setting of targetdir to suit your circumstances. Equally, this procedure targets all files - change the filemask to suit.
The required DEL commands are merely ECHOed for testing purposes. After you've verified that the commands are correct, change ECHO(DEL to DEL to actually delete the files.
method is to simply execute a dir in basic form without directories, sorted in reverse-date order.
Skip the first 10 entries, and delete the rest.
With forfiles I see no chance to accomplish your task of returning the newest (most recent) number of files.
So my idea for this approach is this:
to use dir /B /A:-D /T:C /O:-D to retrieve a bare list (/B) of files (no directories, /A:-D), sorted by creation date (/T:C; if you want to use the last modification date, simply remove the /T:C portion) in decending order (/O:-D), meaning newest items first;
to put over a for /F "eol=| delims=" loop to gather and parse the dir output line by line, meaning file by file, not excluding file names beginning with ; (eol=|, | is illegal for file names) and not splitting file names containing white-spaces like SPACE or TAB (delims=);
to establish a variable that constitutes a counter, incremented per each loop iteration;
to place an if condition inside of the loop to check if the counter reached the desired limit number and in case it is fulfilled, to break the for /F loop by goto;
Here is the related code:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem Define global constants here:
set "TARGETPATH=\path\to\files\*.*"
set /A "TOTAL=10"
set /A "COUNT=0"
for /F "eol=| delims=" %%F in ('
dir /B /A:-D /T:C /O:-D "%TARGETPATH%"
') do (
echo(%%F
set /A COUNT+=1
setlocal EnableDelayedExpansion
if !COUNT! GEQ %TOTAL% (
endlocal
goto :NEXT
) else (
endlocal
)
)
:NEXT
endlocal
exit /B
I toggled the delayed variable expansion within the for /F loop to avoid trouble in case file names contain exclamation marks !, which would get lost in the line echo(%%F in case it is on.
Update
The following code accomplishes the original task of your question, namely to delete files in a given directory but to keep the most recent number of files:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem Define global constants here:
set "TARGETPATH=\path\to\files\*.*"
set /A "TOTAL=10"
set "SKIPOPT=" & if %TOTAL% GTR 0 set "SKIPOPT=skip=%TOTAL% "
for /F "%SKIPOPT%eol=| delims=" %%F in ('
dir /B /A:-D /T:C /O:-D "%TARGETPATH%"
') do (
del /P "%%F"
)
endlocal
exit /B
Since for /F supports a skip= to skip the given number of lines, and so files in our situation, let us make use of it. It is given indirectly here via variable SKIPOPT, which holds the entire option string like skip=10 (given that TOTAL is set to 10). The if %TOTAL% GTR 0 query is implemented for the script not to fail in case TOTAL is 0, because for /F does not accept the option skip=0.
The /P switch at the del command lets appear a prompt Delete (Y/N)? for testing purposes. If you do not want any prompts, simply remove it.
I have a directory with several hundred text files and I need a way to count the combined total number of lines of all the txt files. I'm using Windows and I thought it would be easy enough to find through the command prompt, but the following only returns the number of files:
C:\> dir /b c:\temp | find /c /v “~~~”
This is only an example, but it returned the number of files without "~~~" when I expected it to go through each file and count the total number of lines without ~~~. Any suggestions to get a total count would be greatly appreciated.
#ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir\t w o"
SET /a countfiles=0
SET /a countlines=0
FOR /f "delims=" %%a IN (
'dir /b /a-d "%sourcedir%\*" '
) DO (
SET /a countfiles+=1
FOR /f "delims=" %%c IN ('find /c /v "~~~" "%sourcedir%\%%a"') DO CALL :setcount %%c
)
SET cou
GOTO :EOF
:setcount
IF "%2" neq "" shift&GOTO setcount
SET /a countlines +=%1
GOTO :EOF
You would need to change the setting of sourcedir to suit your circumstances.
For each filename found in the directory, count a file, then deliver to the subroutine setcount the output of the find command, typically
---------- U:\SOURCEDIR\T W O\FILE4.TXT: 3
Since we want the last item in this string, we simply shift the parameter until the second does not exist, hence the first must be the linecount from find, so add it.
I don't usually create .bat file, but I made this little script useful for develop.
I'm using this for reading and creating a list of files contained into a folder:
for /f "delims=|" %%f in ('dir /b C:\src\release\android\') do echo %%f
and I found this about how to create a menu starting from a list of file -> Multiple choices menu on batch file?
Now my question is:
I'd like to create a menu with a list of files contained into that folder which I can select (not multiple selection) by pressing it's relative number on the list, but i don't really know how to merge the two bit of code above.
The final result should work something like:
[1] ..
[2] ..
[3] ..
[4] ..
select file:
and it will install the selected file from the folder.
Any suggestion would be really appreciated.
Thanks in advance
This should work unless you're using a version of Windows that doesn't have choice, like if you're still on XP for some reason.
#echo off
setlocal enabledelayedexpansion
set count=0
set "choice_options="
for /F "delims=" %%A in ('dir /a:-d /b C:\src\release\android\') do (
REM Increment %count% here so that it doesn't get incremented later
set /a count+=1
REM Add the file name to the options array
set "options[!count!]=%%A"
REM Add the new option to the list of existing options
set choice_options=!choice_options!!count!
)
for /L %%A in (1,1,!count!) do echo [%%A]. !options[%%A]!
choice /c:!choice_options! /n /m "Enter a file to load: "
:: CHOICE selections get set to the system variable %errorlevel%
:: The whole thing is wrapped in quotes to handle file names with spaces in them
:: I'm using type because I'm not familiar with adb, but you be able to get the idea
type "C:\src\release\android\!options[%errorlevel%]!"
Improving upon SomethingDark's script to run Python scripts in a user's Document folder (I know, not best practice here for brevity's sake), as it currently wouldn't work when there are more than 10 choices:
#echo off
setlocal enabledelayedexpansion
set count=0
set "choice_options="
for /F "delims=" %%A in ('dir /a:-d /b C:\Users\JohnSmith\Documents\*.py') do (
REM Increment %count% here so that it doesn't get incremented later
set /a count+=1
REM Add the file name to the options array
set "options[!count!]=%%A"
)
for /L %%A in (1,1,!count!) do echo [%%A]. !options[%%A]!
::prompts user input
set /p filechoice="Enter a file to load: "
:: Location of python.exe and location of python script explicitly stated
echo Running !options[%filechoice%]!...
"C:\Users\JohnSmith\AppData\Local\Microsoft\WindowsApps\python.exe" "C:\Users\JohnSmith\Documents\!options[%filechoice%]!"
I'm lookiong for a batch script which let's me count only the amount of files in a certain sub dir.
I have a directory tree with various projects (300+) and I am only looking for the amount of files in a reocurring subdirectory.
Currently I am using mtee(small program to revert cmd output to a txt file) and dir to count the subdirs and do a manual search in excel.
I was wondering if there is a way to do this in with a batch script.
e.g: Every project has the directory proposals and subdirectory no-go proposals. I want to count the amount of files in the no-go proposals from the basis of the directorytree
for /f %%i in ('dir /s/b/a-d "c:\project"^|find /c "\no-go-dirname\"') do ECHO nogocount=%%i
Well, that's the line within a batch file. If you're running it from the prompt, each %% becomes %
do a directory list of all of the filenames, /a-d not directorynames, /s including subdirectories /b in basic form, so no headers or trailers. Filter this with a FIND and /c count the lines that contain the string "\no-go-dirname\" and assign the count to %%i
Try this:
#echo off &setlocal
set "startfolder=x:\proposals\no-go proposals"
set /a counter=0
for /r "%startfolder%" %%i in (*) do set /a counter+=1
echo %counter% files found in "no-go proposals" .
Read HELP FOR and HELP SET and try the following code
#echo off
setlocal enabledelayedexpansion
for /r /d %%d in (*) do (
call :countf "%%d\nogo"
)
goto :eof
:countf
set count=0
for %%f in ("%~1\*") do (
set /a count+=1
)
echo %~1 has !count! files
goto :eof
Good to see so many alternatives, and all of them works seemlessly however this is my version.
dir /s/b /a-d | find /c /v ""
running this command in a directory where you need the file count will return just the count.