.bat - Create a menu from folder file list - windows

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%]!"

Related

How to create folder name without extension of file type using batch script and move in created sub directory?

Help me sir i try more than 100 times but it not exactly works for me.
Currently getting results in wrong way:-
Given below batch script create folder from this file (7101-1- kutana.pdf) name with .pdf extension but not exactly what i need.
Results i need in right way a/q to given below steps
For example
Step 1:-I want to remove 1st five character from file name (7101-1- kutana) and also i want to remove extension from folder name.
Sourcedir=e:\automovesystem\temp
A. source pdf file name :- 7101-1- kutana.pdf
Step 2:-
Create directory under destdir name of 1-(space)kutana and award
B. destdir=e:\automovesystem\prpl
Created directory e:\automovesystem\prpl\1- kutana\award
Step3.check if already folder name available according to step 1 file name.
Step 4: - move same file in same folder which is created in step 2 under sub directory.
#echo off setlocal enableextensions disabledelayedexpansion
Set "sourcedir=e:\automovesystem\temp"
Set "destdir=e:\automovesystem\prpl"
For /f "eol=| tokens=1* delims=-" %%a in ('dir /b /a-d-h "%sourcedir%\*-*" 2^>nul') do (
Md "%destdir%\%%b\award" 2>nul
Move /y "%sourcedir%\%%a-%%b" "%destdir%\%%b\award" )
Endlocal
Additional to your own answer, I probably would have done it a litte more like this:
#Echo Off
SetLocal EnableExtensions
Set "SRC=E:\automovesystem\TEMP"
Set "DST=E:\automovesystem\PRPL"
If Not Exist "%SRC%\" (Exit /B) Else If Not Exist "%DST%\" Exit /B
For /F "Delims=" %%G In ('%SystemRoot%\System32\where.exe "%SRC%":"????-?*-?*.*"
2^>NUL') Do For /F "Tokens=1,* Delims=-" %%H In ("%%~nG"
) Do %SystemRoot%\System32\Robocopy.exe "%%~dpG." "%DST%\%%I\NOTICE" "%%~nxG"^
/Mov 1>NUL 2>&1
All help with this goes to #XionicFire he reworked the whole of this code I'm just posting it for others to use/benefit:
This code comes from a mix of several different people #PrahladDixit & #Compo, the code was not working we couldn't tell why after a LOT of search seems it suffered the usual... "a pro wrote this so no one understands what he did" syndrome, where us worms cannot figure it out, we remade it and organized it so normal human "worms" can understand what its doing and made it a little friendlier so its easier to mod and change as needed, we hope this helps others, works great in windows 11
Code
#ECHO OFF
ECHO This file will create Individual folders inside the current folder using the following Parameters and sort all *.JPG files in current directory accordingly
REM To change target or source directory simply type it in the variable field
SET "SRC=%~dp0"
SET "SRC=%SRC:~0,-1%"
SET "DST=%~dp0"
SET "DST=%DST:~0,-1%"
ECHO.
REM For Diagnostics & Troubleshooting Purposes
ECHO Source: %SRC%
ECHO Destination: %DST%
ECHO Characters: 19
ECHO Where: %SystemRoot%\System32\where.exe "%SRC%":*.jpg
ECHO.
ECHO To Cancel this operation press CTRL-C
PAUSE
SetLocal EnableDelayedExpansion
If Not Exist "%SRC%\" (Exit/B) Else If Not Exist "%DST%\" Exit/B
For /F "Delims=" %%A In ('%SystemRoot%\System32\where.exe "%SRC%":*.jpg') Do (
SET "FNX=%%~nA"
REM Replace 19 for the number of characters from the start of the filename you wish to use as Base for folder creation
SET "FNX=!FNX:~,19!
REM For Diagnostics & Troubleshooting Purposes
REM ECHO !DST!\!FNX!\
If Not Exist "!DST!\!FNX!\" (MD "!DST!\!FNX!" 2>NUL
If ErrorLevel 1 ECHO Unable to create directory !DST!\!FNX!)
If Exist "!DST!\!FNX!\" (MOVE /Y "%%A" "!DST!\!FNX!">NUL 2>&1
If ErrorLevel 1 ECHO Unable to move %%A to !DST!\!FNX!)
)
ECHO ************************ DONE ************************
PAUSE
REM Use in the case of running multiple scripts in a row
REM EXIT/B
I had less knowledge of batch scripting that's why not sleep from yesterday continue
working on to make AutoMoveFilesystem but also i am great thankful to provide stack overflow platform to create this code. i can't able to do without this plateform.
#Echo Off
Set "SRC=E:\automovesystem\TEMP"
Set "DST=E:\automovesystem\PRPL"
SetLocal EnableDelayedExpansion
If Not Exist "%SRC%\" (Exit/B) Else If Not Exist "%DST%\" Exit/B
For /F "Delims=" %%A In ('Where "%SRC%":?????????*.*') Do (Set "FNX=%%~nA"
If Not Exist "%DST%\!FNX:~5,50!\NOTICE" (MD "%DST%\!FNX:~5,50!\NOTICE" 2>Nul
If ErrorLevel 1 Echo Unable to create directory %DST%\!FNX:~5,50!\NOTICE)
If Exist "%DST%\!FNX:~5,50!\NOTICE" (Move /Y "%%A" "%DST%\!FNX:~5,50!\NOTICE">Nul 2>&1
If ErrorLevel 1 Echo Unable to move %%A to %DST%\!FNX:~5,50!\NOTICE))
Timeout -1
Exit/B

Gathering list of file extensions - "The command line is too long" workaround

I am currently using this batch file to scan through a Windows file system and save a .txt document of all the file extensions in that system:
Cmd Line Command:
NameOfBatchFile.bat >List.txt
BatchFile Code:
#echo off
set target=%1
if "%target%"=="" set target=%cd%
setlocal EnableDelayedExpansion
set LF=^
rem Previous two lines deliberately left blank for LF to work.
for /f "tokens=*" %%i in ('dir /b /s /a:-d "\\PathOfMyWindowsDirectory"') do (
set ext=%%~xi
if "!ext!"=="" set ext=FileWithNoExtension
echo !extlist! | find "!ext!" > nul
if not !ERRORLEVEL! == 0 set extlist=!extlist!!ext!:
)
echo %extlist::=!LF!%
endlocal
The code works great on small folders but if I provide it a folder with too many subfolders, the command line will process then provide the following error:
The command line is too long.
The command line is too long.
The command line is too long.
The command line is too long.
The command line is too long.
The command line is too long.
The command line is too long.
The input line is too long.
I can't edit the filesystem to decrease subfolders, does anyone know another way to get this to work?
The problem in your code is the concatenation of elements inside a variable, that can generate a long list of extensions that will end generating a excesively long command line.
#echo off
setlocal enableextensions disabledelayedexpansion
set "target=%~1"
if "%target%"=="" set "target=%cd%"
for /r "%target%" %%a in (*) do if not defined "\%%~xa\" (
if "%%~xa"=="" (echo(FileWithNoExtension) else (echo(%%~xa)
set ""\%%~xa\"=1"
)
endlocal
This uses the environment to store the information of seen extensions by setting a variable for each one. If the variable is not set, this is the first time the extension is found and is echoed to console.
I think this is the fastest way to get the result to this problem.
#echo off
setlocal
set target=%1
if "%target%"=="" set target=%cd%
for /R "%target%" %%a in (*.*) do set ext[%%~Xa]=1
for /F "tokens=2 delims=[]" %%a in ('set ext[') do (
if "%%a" equ "=1" (
echo FileWithNoExtension
) else (
echo %%a
)
)
Previous method may be easily modified in order to get the number of files that have each extension; just modify the set ext[%%~Xa]=1 by set /A ext[%%~Xa]+=1 and modify the tokens in the for /F accordingly.
This gives you a sorted list of all the extensions very quickly.
#echo off
set "target=%~1"
if "%target%"=="" set target=%cd%
dir "%target%" /b /s /a-d |repl ".*(\..*)" "$1" |repl ".*\\.*" "FileWithNoExtension"|sort|uniq >file.txt
This uses a helper batch file called repl.bat (by dbenham) - download from: https://www.dropbox.com/s/qidqwztmetbvklt/repl.bat
This uses a helper batch file called uniq.bat (by aacini) - download from: https://www.dropbox.com/s/71o38a4ljnqgqjh/uniq.bat
Place repl.bat and uniq.bat in the same folder as the batch file or in a folder that is on the path.

Batch reading a file name

Say I have a folder "C:/My Folder" it will have 10 files in it. I need to know how I would set a variable for each file name to an individual variable like:
%File1%
%File2%
%File3%
%File4%
%File5%
%File6%
%File7%
%File8%
%File9%
%File10%
I have looked on a few sites and I have only found it ether setting the names to one variable or only doing it for one file. Does any one know how I could do it for an individual variable. Thanks in advance.
#ECHO OFF
SETLOCAL
SET "sourcedir=c:\sourcedir"
FOR /f "tokens=1*delims=:" %%a IN (
'dir /b /a-d "%sourcedir%\*"^|findstr /n /r "." ') DO (
SET "file%%a=%sourcedir%\%%b"
)
SET file
GOTO :EOF
This should generate and show the list. Your job to set the directory and filemask.

Windows batch file to process camera images

I am trying to create a batch file to take photos off a camera or sd drive (which are specific and don't change.
I then want to move all the *.jpg to a different drive on the company's internal network.
The way it's set up it will look like n:\jobnumberfolder\pictures.jpg
I need the files to be able to be renamed like: "vpi(1).jpg", "vpi(2).jpg" and so on (the same thing you accomplish in Windows by highlighting multiple files and clicking rename.
The batch file will prompt the user for a job number (which will be the folder it will be moved to), and a description (what to name the file).
My programming experience is limited and in php and python, but I do understand the very basics: loops, if-else, arrays,... things like that.
My problem is that with the batch file, I cannot seem to find a good way to create a for loop to get what I want. I think I could do this in python using the os module, but I feel like I'm missing something simple (like a simple command or something I could be using for Windows).
I cannot even get a variable to increment, even with delayed expansion command. Even if I could, would it be possible to add it to the file name? I tried to find an answer for this, but have not been able to.
So my question are:
Can i actually do this in a batch file?
Would it be easier to just write a python script to do it, which will cause me to have to install python on the company's computer? I just want to be able to rename a file with a incrementing number at the end.
Something like this is what I'm looking for
i = 0
name = "whatever"
for each jpg in camera/images
rename each to whatever + i
i+=1
Any help would be appreciated.
Change n:\ in two places and f:\cam-folder\ where needed. It's untested:
#echo off
:loop
cls
echo Enter "jobnumberfolder,description" with comma and no quotes:
echo similar to 986,vpi
set "var="
set /p "var="
for /f "tokens=1,* delims=," %%a in ("%var%") do set "job=%%a"&set "desc=%%b"
echo "%job%" "%desc%" - correct? press enter to continue or N to start again:
set "var="
set /p "var="
if defined var goto :loop
md "n:\%job%\" 2>nul
setlocal enabledelayedexapansion
echo.
set c=0
for %%a in ("f:\cam-folder\*.jpg") do (
set /a c+=1
echo copying "n:\%job%\%desc%(!c!)%%~xa"
copy "%%a" "n:\%job%\%desc%(!c!)%%~xa" >nul
)
echo done
pause
#echo off
setlocal enableextensions enabledelayedexpansion
rem configuration
set "sourceFolder=w:\images"
set "targetFolder=n:\jobs"
rem test if there is something to copy
if not exist "%sourceFolder%\*.jpg" (
echo NO FILES FOUND
goto endProcess
)
:askJob
rem ask job number
set /p "jobNumber=Job Number : "
rem test if no job number
if "%jobNumber%"=="" (
echo NO JOB NUMBER - End of process
goto endProcess
)
rem test for existing job number
if exist "%targetFolder%\%jobNumber%" (
echo DUPLICATE JOB
goto askJob
)
rem ask for description
set /p "description=Description : "
rem test for no description
if "%description%"=="" (
echo NO DESCRIPTION - End of process
goto endProcess
)
rem WARNING - No test for valid job number nor valid description
rem WARNING - Don't shoot your own foot, or add code to validate
rem WARNING - according to your needs
rem create target job folder
set "target=%targetFolder%\%jobnumber%"
mkdir "%target%" > nul 2>nul
rem DO THE COPY
rem Generate a file list (dir), numerate it (findstr /n) and for each line
rem in generated list, split the number from the filename (for with delims)
rem and copy source file to numbered target file
for /f "tokens=1,* delims=:" %%f in ('dir /tc /od /b "%sourceFolder%\*.jpg" ^| findstr /n "^"') do (
echo transfer: "%sourceFolder%\%%g" == "%target%\%description%(%%f).*"
copy "%sourceFolder%\%%g" "%target%\%description%(%%f).*" >nul 2>nul
)
echo FILES COPIED
:endProcess
rem Clean
endlocal
rem and exit
exit /b

Batch File to list folders and allow user selection

I have searched and searched to find a solution to (what feels like) a unique problem. Many
answers here have been quite helpful and have gotten me a long way, but the last bit has me stumped.
My batch file needs to open an executable in a folder with a variable name
This folder may be in one of two directories
This is what I originally had and it works
#ECHO OFF
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
SET DIR1="%USERPROFILE%\AppData\Local\Application Workspace\Profiles"
SET DIR2=C:\Application\SRW\Profiles
IF NOT EXIST %DIR1% (
GOTO PROFILE_2
) ELSE (
GOTO PROFILE_1
)
:PROFILE_1
for /f "delims=" %%A in ('dir %DIR1% /ad /b') do (
set foldername=%%~nxA
)
SET DIR1=%DIR1:"=%
SET DIR=%DIR1%\%foldername%\app.exe
GOTO START_APP
:PROFILE_2
for /f "delims=" %%A in ('dir %DIR2% /ad /b') do (
set foldername=%%~nxA
)
SET DIR=%DIR2%\%foldername%\app.exe
GOTO START_APP
:START_APP
START "" /b "%DIR%"
:EOF
ENDLOCAL
EXIT
Then I was thrown a curveball when I discovered that some users may have multiple profiles in the variable profile folder and they need to be able to select which one to use for that given task. Now I have a variable profile folder and either one or multiple variable profiles within that folder.
I have found code to list the folder names and display them in the command window for selection.
#echo off
cls
setlocal EnableDelayedExpansion
set /a count=0
for /d %%d in (*) do (
set /a count+=1
#echo !count!. %%d
)
setlocal DisableDelayedExpansion
set /P selection="select folder number:"
I also found this routine which allows the user to select a file from a list then it is supposed to translate that file name into a variable.
Batch Script Programming -- How to allow a user to select a file by number from a list of files in a folder?
Unfortunately, I cannot get the example in the link to work as is and I have no idea how to make it work with folder names as the folder name example and the file name example are close but not close enough for me to understand what to do. And even if it somehow does manage to work, how then can I make such a routine work within the original code posted above?
In addition, I really don't want the user to be forced to make a folder selection if there is only one folder. If only one folder exists, it should be placed into the folder name variable automatically and nothing displays to the user at all.
Is what I'm trying to do even possible at all?
Any help is most appreciated.
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
::
:: Set count-of-targets and application name
::
SET /a targets=0
SET appname=app.exe
SET "dots=..."
::
:: clear all "$" variables
::
FOR /f "delims==" %%i IN ('set $ 2^>nul') DO SET "%%i="
::
:: look for app.exe in (1) userprofile... (2) \application\srw...
::
SET dir1="%USERPROFILE%\AppData\Local\Application Workspace\Profiles"
SET dir2="C:\Application\SRW\Profiles"
:: My testing - my directory names
SET dir1="c:\sourcedir"
SET dir2="C:\destdir\test dir"
FOR %%s IN (%dir1% %dir2%) DO (
FOR /f "delims=" %%i IN ('dir /s /b "%%~s\%appname%"') DO ( CALL :process "%%~dpi"
)
)
::
:: Now have TARGETS=#hits; $_n=full pathname; $n=directoryname
::
IF %targets%==1 SET mychoice=1&GOTO chosen
::
:: repeat a menu
::
:again
CLS
FOR /l %%i IN (1,1,%targets%) DO (
IF %%i lss 10 (ECHO(%%i%dots%%dots:~0,1%!$%%i!) ELSE (ECHO(%%i%dots%!$%%i!)
)
SET mychoice=
SET /p mychoice="Please choose 1..%targets% : "
IF NOT DEFINED $_%mychoice% GOTO again
:chosen
CALL SET application="%%$_%mychoice%%%%appname%"
ECHO START "" /b %application%
GOTO :EOF
::
:: Parameter is quoted-full-pathname
::
:process
SET /a targets+=1
SET $_%targets%=%~1
SET $=%~1
FOR %%n IN ("%$:~0,-1%") DO SET $%targets%=%%~nxn
GOTO :eof
From what you've said, this should work.
First steps are to set up. Set the number of targets found and the real application name and clear out any variablenames that start "$".
Next step is to specify the directories to use. I simply copied yours, then overrode those settings with settings to suit my machine - you'd need to delete those overriding lines, of course. Note that the names should be set quoted...
Next, scan from each of the directories for the application. Each time an instance is found, call :process passing the full -terminated pathname.
:process increments the count of targets found and sets the variable $_n to the full pathname passed (dequoted) It then sets $ to the dequoted-full-pathname and uses a syntax-trick to have FOR find the application's immediate directory. %$:~0,-1% is the full pathname minus the last character - the \ so the results looks like a filename. That "filename" is then assigned to $n
Once the directory-scans are finished, %targets% will contain the er, number of targets. If that's 1, then we have all we need - we can only select target number 1, so that's chosen for us.
Otherwise, clear the screen and display a number of lines - %targets% to be precise. The format isn...immediatedirname` and an extra dot is added if the number of targets is less than 10 so that a long list will line up nicely.
Then ask for a line number.
At this point, the only $_ variables that exist are $_1..$_%targets% so if $_%mychoice% exists, it must be a valid choice. If it's not defined, then repeat the question...
CALLing SET application="%%$_%mychoice%%%%appname%" first parses the command, then parses it again. After the first parse, the line becomes (if mychoice=3) SET application="%$_3%app.exe" so on the second occasion,application` is properly set to the full fulename of the application - and quoted.
There wasn't much point in my starting the app, since it doesn't exist, so I just echoed it.
Given the extended requirement:
You's probably be starting this from a shortcut. Suppose you run that shortcut minimised and insert after the SETLOCAL
SET "poweruser=%1"
Add, after
IF %targets%==1 SET mychoice=1&GOTO chosen
the line
IF NOT DEFINED poweruser START "%username% - poweruser" "%~dpnx0" poweruser&GOTO :EOF
And change the
GOTO :EOF
just prior to the label :process to
EXIT
So that if it wasn't run in poweruser mode (therefore poweruser is NOT defined) AND %targets% is NOT 1 (I'm presuming it won't be 0) Then this user hasn't been set as a poweruser in the shortcut, but does have more than one target, so the job is restarted in poweruser mode (ie. maximised.)
Note that it doesn't actually matter what the string is after the "~dpnx0" - so long as it's a string. I just used poweruser What it does is tell the batch that it's being run in a normal window, not minimised.
For powerusrs, you could if you like set the shortcut to normal window or maximised AND put a parameter in the command line after the batchname, which will marginally quicken the procedure. Leaving it without parameters and minimised would suit ALL users as it will auto-adjust if more than 1 target is found.
I have tried this. It worked for me.
I answered your question in two steps. In the first one I translated your original code into a more readable one. Here it is:
#ECHO OFF
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
SET "DIR1=%USERPROFILE%\AppData\Local\Application Workspace\Profiles"
SET DIR2=C:\Application\SRW\Profiles
IF NOT EXIST "%DIR1%" (
for /f "delims=" %%A in ('dir %DIR2% /ad /b') do (
SET DIR=%DIR2%\%%~nxA\app.exe
)
) ELSE (
for /f "delims=" %%A in ('dir %DIR1% /ad /b') do (
SET DIR=%DIR1%\%%~nxA\app.exe
)
)
START "" /b "%DIR%"
ENDLOCAL
EXIT
You should check first that previous code is equivalent to your original one.
In the second step I added the profile selection to the previous code:
#ECHO OFF
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
SET "DIR1=%USERPROFILE%\AppData\Local\Application Workspace\Profiles"
SET DIR2=C:\Application\SRW\Profiles
IF NOT EXIST "%DIR1%" (
for /f "delims=" %%A in ('dir %DIR2% /ad /b') do (
SET DIR=%DIR2%\%%~nxA\app.exe
)
) ELSE (
call :SelectProfile
)
START "" /b "%DIR%"
ENDLOCAL
EXIT
:SelectProfile
rem Get a list of folders in User Profile dir
set count=0
for /f "delims=" %%A in ('dir %DIR1% /ad /b') do (
set /A count+=1
SET DIR[!count!]=%DIR1%\%%~nxA
)
rem Initialize the selected profile
set select=1
if %count% equ 1 goto endSelection
rem Show the profiles menu
cls
echo Available profiles:
echo/
for /L %%i in (1,1,%count%) do echo %%i- !DIR[%%i]!
echo/
rem Let's the user to select the profile
:select
set select=1
set /P "select=Enter number of desired profile [first one]: "
if not defined DIR[!select!] goto select
:endSelection
SET DIR=!DIR[%select%]!\app.exe
exit /B
Please note that previous code fail if the user enter spaces in the answer. This detail may be fixed, if needed.

Resources