Link to home
Start Free TrialLog in
Avatar of Ryan Bennett
Ryan BennettFlag for United States of America

asked on

Batch script to find a file and run it, if multiple matches are found list them to choose from...

Hello All,

 I have a batch file that I now need to add the ability to search for a file based on a 3 character code the user will be prompted to enter, once that file is found, open it. Simple right?! However there will be many files with that same 3 character code in the name, so if multiple matches for that code are found, is there a way to dynamically create a list for the user to choose which one of those is the appropriate file to open?

The file names look like: "City-Department-001.reg"

There are spaces in many of the files names, and all the 3 character codes are alphanumeric with a preceding hyphen, and all files are a .reg extension. And the files will be in a sub folder of the folder that contains the batch file.

It's still early, so if I haven't explained myself well, please feel free to ask for better information.

Thanks very much,
RBennett
Avatar of John Gobert
John Gobert
Flag of United States of America image

Sounds like this will be fun :)

I found the code below which isn't everything you need but it should help.  It's the code to create a user selection list based on files found in a folder.  It can be expanded on to meet your needs... I'll keep working on it but I figured I'd share this part now in case you or anyone else wants to jump in and help build it out.  

Credit for the following code goes to:  StackOverflow.com - Fred Bollack

@ECHO OFF
SET index=1

SETLOCAL ENABLEDELAYEDEXPANSION
FOR %%f IN (*.*) DO (
   SET file!index!=%%f
   ECHO !index! - %%f
   SET /A index=!index!+1
)

SETLOCAL DISABLEDELAYEDEXPANSION

SET /P selection="select file by number:"

SET file%selection% >nul 2>&1

IF ERRORLEVEL 1 (
   ECHO invalid number selected   
   EXIT /B 1
)

CALL :RESOLVE %%file%selection%%%

ECHO selected file name: %file_name%

GOTO :EOF

:RESOLVE
SET file_name=%1
GOTO :EOF

Open in new window

Question... will all of the files be in the one subfolder or will there be additional subfolders or paths to contend with?

Do you already have the code written for whatever it is you want to happen when the user makes their selection?

I'm pretty close to wrapping up a working version depending on your response to my first question.
Avatar of Ryan Bennett

ASKER

...All the .reg file should all be in one folder, but in a sub folder of the folder that contains the batch file.

...No I don't have any code written yet for this particular function of the batch file, basically because I just found that I would have to do it this way and after racking my little brain, I couldn't wrap my head around it

Thanks for your help.
Ok... this isn't done yet... but it is a little farther along.

You'll need to update line 5 FOLDERNAME to be the name of the subfolder that your .reg files are in.  Once that's updated this script will do the following:

Ask the user for the search string
Search the folder for all reg files with the search string in the filename
Store the filenames of any matching files in a temp file
Loop through each line of that text file to present the selection list to the user
Accept input from the user for which file they want
Currently just responds with a confirmation of what file you selected
Deletes the temp file

There's more to be done... needs error handling and such for sure... but definitely give it a try.  I have a folder with a bunch of test files I made just to get this built.  It is working for me right now as laid out above but as I said there's more to be done.  

Thoughts?

@ECHO OFF
SET index=1
SET /P filesearchstring="Enter search string:"
SET TMPFILE=tempfile-%RANDOM%-%TIME:~6,5%.tmp
DIR /b FOLDERNAME\*%filesearchstring%*.reg > %TMPFILE%

SETLOCAL ENABLEDELAYEDEXPANSION
FOR /F "tokens=1,2* delims=," %%f IN (%TMPFILE%) DO (
   SET file!index!=%%f
   ECHO !index! - %%f
   SET /A index=!index!+1
)

SETLOCAL DISABLEDELAYEDEXPANSION

SET /P selection="select file by number:"

SET file%selection% >nul 2>&1

IF ERRORLEVEL 1 (
   ECHO invalid number selected   
   EXIT /B 1
)

CALL :RESOLVE %%file%selection%%%

::Your selected filename is now captured as %file_name%

ECHO selected file name: %file_name%

echo y | del %TMPFILE%

GOTO :EOF

:RESOLVE
SET file_name=%1
GOTO :EOF

Open in new window

Looks like it is really close, but there are a few issues...

 First, the script lists the files that is finds correctly, but when I select one from the list it builds for me, it does not include the space in the name once I select it from the list. Make sense? The name is displayed in the list correctly, but when I select it, it echos "selected file name:" it only displays the name of the file up to the first space, not the complete name.

Second, there will be other Techs that will be using the finalized batch file and there maybe different names given to the sub folder that contains the .reg files. So can the search string be changed to reflect an unknown name of the sub folder? I thought maybe just a /s in the search string would work so I tried changing it to ... DIR /b /s *%filesearchstring%*.reg" > %TMPFILE%  but then got the full path and the file name which is not at all desirable. Any thoughts on that?

Thanks again.
SOLUTION
Avatar of John Gobert
John Gobert
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
You're fine, I got busy myself.

Ok I have tried this version and now it can't find any .reg files unless I copy the batch file into the same folder as the .reg files.

Also, when there is only 1 match found for the text entered by the user it displays the 1 item found as a list to choose from instead of just opening the 1 item. I really need it to just open the file if there is only 1 item found to match the string of text entered by the user, otherwise if there are more than 1 items then they will need a list to choose from.

Thanks for sticking with this.
Hi,

Sorry I haven't posted back yet... finally got some sleep last night... I'll be working on the batch file again this afternoon and will look at incorporating the items you mentioned in your last post.  Didn't realize you wanted to auto-select if only one was found... I'll probably leave that for last so that I can work out the other big ticket items.  I'll circle back to that once we get a working script.

Have you made any headway on any parts?  or are you working on it at all?  Just making sure we're not working in two different directions...  if you have any updates let me know so I can update my side.
Ok, I have been working on it on and off today and have kinda made a mess of it playing around. Sorry to do that to ya, but until I get something worked out, I get a little messy.

 I don't have a lot of comments in there but I think you can tell what I have been doing. I've got it to search though sub folders no matter the names of them, and I got it to count how many matches of the files it finds with the text entered by the user. And can get it to apply the reg file if there is only one match found. However, if there are more than 2 matched found the function that builds the list will only throw 2 of them in a list even though the temp file has all the correct matches in it.

I reworked some of your commands and just commented yours out so you can see both. Have a look and lemme know what you think is going on.

Thanks.

@ECHO OFF
setlocal enableextensions 
setlocal enabledelayedexpansion

SET index=1
set /A mtchcnt=0

:: Create random temp filename to hold our file list
::SET TMPFILE=tempfile-%RANDOM%-%TIME:~6,5%.tmp

::Create temp file to hold our file list
SET TMPFILE=tempfile.txt

::if temp file exists before the batch is executed remove it first
if exist %TMPFILE% echo y | del %TMPFILE%

:: Prompt user for the string needed to search for files
SET /P filesearchstring=Enter search string: 

:: Send output of DIR /b search using search string to tempfile.
:: Then count how many files found to match the search criteria.
::DIR /b *%filesearchstring%*.reg /s > %TMPFILE%

for /f "tokens=* delims=" %%a in ('dir /s /b "*%filesearchstring%*.reg"') do (
    echo %%~nxa>>%TMPFILE%
    set file_name=%%~nxa
    set fldrpath=%%~dpa
    set /A mtchcnt=!mtchcnt!+1
    )

::If there is only one match to the search apply reg file.
::if more than one then build a list to choose from.   
echo MatchCount = %mtchcnt% 
if "%mtchcnt%" equ "1" goto ApplyReg
goto CreateList


:CreateList

::FOR /F "tokens=1,2* delims=," %%f IN (%TMPFILE%) DO (

:: Create & display user selection list.  Enclosing filename in " " so filename with spaces are preserved
for /F "tokens=*" %%f in ('findstr /i /c:"%filesearchstring%.reg" %TMPFILE%') do (
   SET file!index!="%%f"
   ECHO !index! - "%%f"
   SET /A index=!index!+1
)

echo Index Count = !index!

:: Prompt for user file selection
SET /P selection=select file by number:

:: Use user input to select filename and pass to file_name variable
SET file%selection% >nul 2>&1

:: If the user enters an invalid option, throw an error
if errorlevel 1 goto CreateList
::IF ERRORLEVEL 1 (
::   ECHO invalid number selected   
::   EXIT /B 1
::)

CALL :RESOLVE %%file%selection%%%

::Your selected filename is now captured as %file_name%
ECHO selected file name: %file_name%
goto ApplyReg

:: Delete the temp file we created to hold the file list
echo y | del %TMPFILE%
pause
GOTO :EOF

:RESOLVE
SET file_name=%1

pause
GOTO :EOF

:ApplyReg

::regedit /s "%fldrpath%%file_name%"
echo Applying Reg File - "%fldrpath%%file_name%"
pause
goto :EOF                                            

Open in new window

I forgot to say that if there are more than 2 matches found, it builds the list using only the last 2 entries of the temp file.
Ok, this version appears to be working as far as passing all the correct information around where it needs to go I believe. The only hang up now is the quotes, they are messing up the final file name after everything is put back together, so that the regedit command will not be able to find the file because the name now has quotes in it. I need ot be able to strip those out but I am not sure I know how to do that.

I really got into a fast attack on this in between things today so I may not have all the comments in there like  I should sorry.

@ECHO OFF
setlocal enableextensions 
setlocal enabledelayedexpansion

SET index=1
set /A mtchcnt=0

:: Create random temp filename to hold our file list
::SET TMPFILE=tempfile-%RANDOM%-%TIME:~6,5%.tmp
SET TMPFILE=tempfile.txt

if exist %TMPFILE% echo y | del %TMPFILE%

:: Prompt user for the string needed to search for files
SET /P filesearchstring=Enter search string: 

:: Send output of DIR /b search using search string to tempfile.
:: Then count how many files found to match the search criteria.
::DIR /b *%filesearchstring%*.reg /s > %TMPFILE%

for /f "tokens=* delims=" %%a in ('dir /s /b "*%filesearchstring%*.reg"') do (
    echo %%~nxa>>%TMPFILE%
    set file_name=%%~nxa
    set fldrpath=%%~dpa
    set /A mtchcnt=!mtchcnt!+1
    )

::If there is only one match to the search apply reg file.
::if more than one then build a list to choose from.   
echo MatchCount = %mtchcnt% 
if "%mtchcnt%" equ "1" goto ApplyReg
goto CreateList

:CreateList

:: Create & display user selection list.  Enclosing filename in " " so filename with spaces are preserved
for /f "tokens=* delims=" %%f in (%TMPFILE%) do (
   SET file!index!="%%f"
   ECHO !index! - "%%f"
   SET /A index=!index!+1
)

 echo Index Count = !index!

:: Prompt for user file selection
SET /P selection=select file by number:

:: Use user input to select filename and pass to file_name variable
SET file%selection% >nul 2>&1

:: If the user enters an invalid option, throw an error
if errorlevel 1 goto CreateList
::IF ERRORLEVEL 1 (
::   ECHO invalid number selected   
::   EXIT /B 1
::)

CALL :RESOLVE %%file%selection%%%

::Your selected filename is now captured as %file_name%
ECHO selected file name: %file_name%
goto ApplyReg

:: Delete the temp file we created to hold the file list
echo y | del %TMPFILE%
pause
GOTO :EOF

:RESOLVE
SET file_name=%1

pause
GOTO :EOF

:ApplyReg

::regedit /s "%fldrpath%%file_name%"
echo Applying Reg File - %fldrpath%%file_name%
pause
goto :EOF                                            

Open in new window

Just finished with a server cutover for a customer... I'm looking at this now... give me a few and I'll post back.
ASKER CERTIFIED SOLUTION
Avatar of oBdA
oBdA

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
I believe I have found a fix to the quotes in the file name. I just needed to change line 70 of my last post to SET file_name=%~1
After that the batch file works and the correct reg file is applied.

oBdA: your reply works up to the point it would echo which reg file it was going to apply then it would exit. I played around with it and found it was also leaving the quotes in the file name as well.
Avatar of oBdA
oBdA

Yes, it's currently supposed to only echo; that's what I described above: "It's currently in test mode and will only display the "reg import" command it would normally run; remove the uppercase ECHO in line 31 to run it for real".
Quotes will only be added around the last "echo" and for the argument for the reg.exe command, where they are required; so if you see the following, then everything is as it should be:
Importing "City-Department-001.reg" ...
reg.exe import "<ScriptFolder>\City-Department-001.reg"

Open in new window

Although jpgobert didn't give a complete solution, or even stick with it all the way through, I was pointed in the right direction and besides it forced me to think and learn how to do a lot of it for myself,  and so I feel pretty good about awarding some points to the direction he was leading me.

However the most complete solution was given by oBdA. Though I did change the for loop on line 13 to dir /b /s "%FileMask%" and I rem'd out the filefolder variable throughout the batch file so that it would find the file no matter the folder name.

Thanks very much or sharing your skills.

RBennett