1

I am trying to create a menu with submenus which their names without extension come from the directory. However, I am unable to make a variable for choice as number. This code does not work anyhow. I would also want to display a number at the beginning of each file name in the menu; in fact, number of the files will also be one of the number that user selects as input. I could not overcome the problem.

@echo off
cd C:\Users\Murray\Documents\ConfigFiles\
for /f %%A in ('dir /a-d-s-h /b *conf ^| find /v /c ""') do set count=%%A
echo File count = %count%

for %%F in ("C:\Users\Murray\Documents\ConfigFiles\*.conf") do echo %%~nxF
set choice=
set /C /N="Please choice: " 

if "%choice%" == "%count%" goto SUBMENU
if NOT EXIST "C:\Users\Murray\Documents\ConfigFiles\%choice%" goto NOFILE

:SUBMENU
Echo You are here

goto end

:NOFILE
echo %choice% could not be found.

goto END

:end

Any help will be appreciated.

Murray
  • 57
  • 7
  • 2
    This is not a valid command: `set /C /N="Please choice: "`. I would advise you to read the help file for the command you are trying to use before attempting to use options that do not exist. – Squashman Sep 01 '21 at 22:39
  • I did but could not find a solution to overcome this: If I set number of choices like this CHOICE C/ 12345 it works with errorleves, but number of choices must be determined to the number of files. – Murray Sep 01 '21 at 22:48
  • 1
    You never use the `CHOICE` command in your code. The choice command would also be limited to 9 choices only if you are using numbers. If you use Letters you could have 52 choices because you could have upper and lower case. So if you want a dynamic menu with a max limit of 9 file choices then this is question and answer you need to look at. [Create a menu from folder file list](https://stackoverflow.com/questions/30592253/bat-create-a-menu-from-folder-file-list) – Squashman Sep 01 '21 at 22:55
  • I will take a look at the URL. However, what if 90 files in my folder exist? then, this means that user cannot select option 11. What can I use to pass over this limitation? – Murray Sep 01 '21 at 23:05

2 Answers2

2

Batch's limitations are to blame for sub-par corrections to this question. Here's the best I could whip up in a few seconds:

@echo off
:one
cls
cd C:\Users\Murray\Documents\ConfigFiles\
 for %%F in ("C:\Users\Murray\Documents\ConfigFiles\*.conf") do echo %%~nxF
echo.
echo Enter Configuration Name:
set/p "prompt=>"
if exist %prompt%.txt goto :two
if exist %prompt% goto :two

cls
echo File not found
pause >NUL
goto :one

:two
cls
REM When file is found, this code will run
pause >NUL

The set command does not prompt for user input unless specified with the /p switch. To make your code more friendly, i'd also recommend to prompt for the filepath earlier on in the code.

EDIT: A few alternative solutions: Declare the 9th option of the prompt of the choice command as a "second page" or "more" option. This would really be a pain for the user in a directory with tens or hundreds of files. Another; you can assign an integer to each file that matches your quasi-query and echo them before each filename on the screen, then allow the user to input the number to get that file. That seems fairly efficient, and if you'd like to explore one or both of those alternates I can help (if you need it).

oh no
  • 118
  • 6
  • That is really great! It works flawlessly. Thank you very much. In fact, I would like user to select an option among the numbers because file names may long. Help is always welcomed. At this point, @Compo 's touch to the solution is what I am exactly looking for besides yours. – Murray Sep 02 '21 at 07:09
2

Here's a quick example of a method touted in the answer by on no. It will print a number to the screen followed by the names of each file matching file extension, so will allow a large number of matching files, (although the end user may have to scroll a long list). Once a file is chosen, your end user then just types its corresponding number. The code should not proceed beyond the input request until a number matching one in the list is ENTERed.

@Echo Off
SetLocal EnableExtensions DisableDelayedExpansion

Set "src=C:\Users\Murray\Documents\ConfigFiles"
Set "ext=.config"

If Not Exist "%src%\*%ext%" Echo No file matches.& GoTo End
For /F "Delims==" %%G In ('"(Set #) 2>NUL"') Do Set "%%G="
For /F "Delims==" %%G In ('%SystemRoot%\System32\wbem\WMIC.exe OS Call /? ^|
 %SystemRoot%\System32\find.exe "=="') Do Set "HT=%%G"
For /F "Tokens=1* Delims=:" %%G In ('Dir /B /A:-D "%src%\*%ext%" 2^>NUL ^|
 %SystemRoot%\System32\findstr.exe /E /I /L /N "%ext%"'
) Do Set "#%%G=%%H" & Echo( %%G.%HT:~-1%%%H
If Not Defined #1 Echo No file matches.& GoTo End

:Opt
Echo(
Set "HT=" & Set "opt="
Set /P "opt=Enter the number for your chosen file>"
If Not Defined opt (GoTo Opt) Else Set "opt=%opt:"=%"
Set # | %SystemRoot%\System32\findstr.exe /B /L "#%opt%=" 1>NUL || GoTo Opt
SetLocal EnableDelayedExpansion
For %%G In ("!#%opt%!") Do EndLocal & Set "opt=%%~G"

@Rem Your code goes below here

Echo(& Echo You Selected %opt%

@Rem Your code ends above here

:End
Setlocal EnableDelayedExpansion & For /F "Tokens=1,2" %%G In ("!CMDCMDLINE!"
) Do Endlocal & If /I "%%~nG" == "cmd" If /I "%%~H" == "/c" Echo(& Echo Press^
 any key to exit.&Pause 1>NUL

All you need to do is to modify the variables values on lines 4 and 5, if necessary, in order to test it. I will not be supporting changes or additions beyond that. Once you have tested the code, you may insert your code between lines 25 and 29, replacing the example line I left there for your test.

Compo
  • 36,585
  • 5
  • 27
  • 39
  • Outstanding. Thank you very much for your work. It is great. I do also need to mention @oh no solution works, too, and gives me some hints about how to handle further situations. – Murray Sep 02 '21 at 07:13
  • Only one very little question. I would like to customize the menu display file names without extension? Which variable can I change to display file names as options while still searching files with their extension in the directory? – Murray Sep 02 '21 at 07:41
  • 1
    @Murray, to print only the file basenames to the list, change the last character on line `13` to these three, `~nH` – Compo Sep 02 '21 at 09:27
  • Hi @Compo I changed to this `%%G.%HT:~-1%%%nH` did not work Where am I missing? – Murray Sep 02 '21 at 09:36
  • 2
    The tilde, `~`! i.e. `%%G.%HT:~-1%%%~nH`. – Compo Sep 02 '21 at 09:46
  • Hi @Compo. I inserted my code to copy the file from selected option. `Echo(& Echo You Selected %opt% cd "C:\Users\Murray\Documents\ConfigFiles" for /f "delims=" %%a in ('dir /b /a-d') do copy "%opt%" "C:\Users\Murray\Documents"` Yes, it works, it copies the file selected via menu to the target directory. However, in cmd windows, i see `1 file(s) copied.` saying 13 times. What is the reason of it? – Murray Sep 02 '21 at 22:57
  • 1
    That question is completely unrelated to my answer, it is related only to the code you've added yourself. Please do not abuse those who have solved your question by treating them as your personal support agent. You do not need all of that code, `%opt%` is already defined as a variable, so use it. Replace `Echo(& Echo You Selected %opt%`, _(as you've already been told)_, with `Copy /Y "%src%\%opt%" "%src%\.." 1>NUL` and it will copy the file up one level as your code indicates, whilst supressing the`1 file(s) copied.` output too! – Compo Sep 03 '21 at 01:44
  • Thank you for support @Compo you are right. Please accept my apologies, I am going to carefully follow community rules so far. – Murray Sep 03 '21 at 04:54