batch - attach variable to items on a list - batch-file

Using the following code I am able to create a list of folders in a directory -
Setlocal EnableDelayedExpansion
set /p pattern=Enter Search Term:
echo.
dir /b /A:D %pattern%*
For example, if the user inputs con, the result may be
-construction1
-construction2
-construction_Docs
etc.
I would like to be able to attach a value to each item eg.
1_Construction1
2_Construction_Docs
etc.
Am I correcting in thinking that I would have to output the initial list I created to a .txt and then read and attach a variable to every line?
The end result would be a user being able to select one of the items based on the number we attach to it, and then have further actions being taken on that item.

dir /b /A:D %pattern%*|find /n /v ""
would yield
[1]construction1
[2]construction2
[3]construction_Docs
or
dir /b /A:D %pattern%*|findstr /n /v ":"
would yield
1:construction1
2:construction2
3:construction_Docs
You could then try
set /a max=0
for /f "delims=:" %%a in ('dir /b /A:D %pattern%*^|findstr /n /v ":" 2^>nul') do set /a max=%%a
which would set max to 0 if none found or the maximum number
The ^ tells batch that the pipe/> is part of the command to be executed
2>nul suppresses error messages in the case of no matches found
It's then a simple matter of
if %max%==0 echo none found&goto askagain
set /p "selection=Please choose [1..%max%] ? "
for /f "tokens=1*delims=:" %%a in ('dir /b /A:D "%pattern%*"^|findstr /n /v ":" 2^>nul') do if "%%a"=="%selection%" set "dirselected=%%b"&goto found
echo %selection% is invalid
goto askagain
:found
echo %dirselected% selected.
to make a complete job.

This task is relatively simple to achieve if you use the right tools, like an array:
#echo off
setlocal EnableDelayedExpansion
set /P "pattern=Enter Search Term: "
echo/
rem Get the folders, store they in the array and show the menu
set "num=0"
for /D %%f in (%pattern%*) do (
set /A num+=1
set "folder[!num!]=%%f"
echo !num!- %%f
)
if %num% equ 0 echo No folders found & goto :EOF
echo/
:selectFolder
set /P "num=Enter the desired folder: "
echo/
if not defined folder[%num%] goto selectFolder
set "item=!folder[%num%]!"
echo Folder selected: %item%
For further details on array management in Batch files, see this post.

Related

feed command output into for /f

Is it possible to pipe the command output to the following batch file as its input?
I'd like to feed output from commands such as dir c:\temp |find "05" |find "new" to the following batch file. Because my command have many variations and I don't want to edit the batch file every time I need it, thus, I'm looking for a way to feed the command output directly to the batch file, instead of having the batch file generate its input using dir /b. Basically, what I'd like to achieve is to find from a list of files (generated using the dir command) the file whose name contains the highest number (achieved using the batch file.) Example:
today123.txt
today456.txt
tomorrow123.txt
tomorrow456.txt
With the dir command, I can filter off today or tomorrow, leaving only two files. Then, feed these two files to the batch file and have it select the one which has 456 in the file name. Of course, this is a simplified example. I may have more files and more groups than those in the example.
for /f %%a in ('dir /b ^|sort /r ^|findstr /r [0-9]') do (
set "filename=%%a"
goto done
)
:done
echo the highest found is %filename%
exit /b 0
There are quite a number of ways. This is one of them:
#echo off & set filename=
if "%~5" == "" set "myfind=dir /b ^| find "%~2" ^| find "%~3" ^| find "%~4" ^|sort /r ^|findstr /r [0-9]"
if "%~4" == "" set "myfind=dir /b ^| find "%~2" ^| find "%~3" ^|sort /r ^|findstr /r [0-9]"
if "%~3" == "" set "myfind=dir /b ^| find "%~2" ^|sort /r ^|findstr /r [0-9]"
if "%~2" == "" set "myfind=dir /b ^|sort /r ^|findstr /r [0-9]"
pushd "%~1"
for /f %%a in ('%myfind%') do (
set "filename=%%a"
goto done
)
:done
popd
if not defined filename echo Not match found & exit /b 1
echo the highest found is %filename%
exit /b 0
Typically you would run it as:
batch-file-name.cmd "C:\path\to\search" "search1" "search2" "search3"
for instance, using your example:
batch-file-name.cmd "c:\temp" "05" "new"
or even extend the search:
batch-file-name.cmd "c:\temp" "05" "new" ".txt"
How it works:
We set the search string each time in the case an additional find command is required. for now we have up to three finds and one path, but it can be extended to more. You have to set them in descending order though.
I also added an additional statement if not defined filename to ensure you are alerted if a find is not matched.
The following gets the highest of a given group:
#echo off
setlocal enabledelayedexpansion
set "search=today"
set "max=0"
for %%a in (%search%*.txt) do (
set "name=%%~na"
set "number=!name:%search%=!"
if !number! gtr !max! set /a max=number
)
echo max number for %search% is %max%
set "highest=%search%%max%.txt"
echo %highest%
Attention, there is no errorchecking at all, so it depends on the correct format of the file names. (errorchecking can be added when needed)
To get the search string as a parameter, simply replace set "search=today" with set "search=%~1"

batch file, string manuplutation with dir command

Trying to get this to work.
Getting this line from dir: 3 File(s) 7,332,731,128 bytes and trying to just get the number of files to use for addition.
#Echo ON
dir %1 /a:h | find "File(s)" > hidden.txt
dir %1 | find "File(s)" > reg.txt
set /p hidden=<hidden.txt
echo %hidden%
IF /I "%hidden%"=="File Not Found" (
Set hidden = 0
) Else (
Set hidden=%hidden~-29%)
echo %hidden%
Set /p reg=<reg.txt
IF /I "%hidden%"=="File Not Found" (
set reg = 0
) ELSE (
Set reg=%reg~-29%)
set /a total = %reg% + %hidden%
Echo The total number of files in the %1 directory is: %total%. This includes hidden files.
Echo.
Echo The total number of non-hidden files in the %1 directory is: %reg%.
Echo.
Echo The total number of hidden files in the %1 directory is: %hidden%
you don't need temp files which only will slow down your script:
if you want to count the hidden files try this
#echo off
set counter=0
for /f %%# in ('dir /a:h-d "%~1"') do (
set /a counter=counter+1
)
echo hidden files=%counter%
to count all files
#echo off
set counter=0
for /f %%# in ('dir /a:-d "%~1"') do (
set /a counter=counter+1
)
echo all files=%counter%
This is just another For loop option:
#For /F %%A In ('Dir/AH-D-L "%~1" 2^>Nul') Do #If Not "%%A"=="0" Set "fileCount=%%A"
#Echo %fileCount%
#Pause
Remove -L, if you wish not to exclude junction points from your file count.
I've got the same result with just two FOR loops. Using sentences between single quotes inside the parentheses we can execute commands and store results.
I've left the same Result Text just to let you compare and see if this is what you're looking for:
CODE:
#echo off
setlocal
for /f %%A in ('dir "%~1" /a-h-d /b ^| find /V /C ""') do set "visCount=%%A"
for /f %%A in ('dir "%~1" /ah-d /b ^| find /V /C ""') do set "hidCount=%%A"
set /a totalCount = visCount + hidCount
echo.
echo The total number of files in the %1 directory is: %totalCount%. This includes hidden files.
echo.
echo The total number of non-hidden files in the %1 directory is: %visCount%.
echo.
echo The total number of hidden files in the %1 directory is: %hidCount%
With /B parameter of DIR command I only get one line per file and no more text, and with /A I can select Hidden or not files and no directories.
Then SET /A command let us use arithmetics operations.

Batch file for counting the files with same initial name and moving them

Is it possible to do this?
In a folder i have files with same initial names
Example:
Main folder
-Quest2323231.txt
Quest2343434.txt
Quest2343435.txt
Fund103.txt
Fund102.txt
I have a config file (abc.config) in which i have name of file on which i need to count and move them . If the count is more than 2 then i need to move them.
In this case for e g I need to find files which have name as 'Quest'
Appreciate you help on this.
#echo off
setlocal enableextensions
set "number="
for /f "tokens=1" %%a in (
'dir /a-d /-c "c:\mainfolder\quest*" 2^>nul^|findstr /b /c:" "'
) do if not defined number set "number=%%a"
if not defined number set "number=0"
echo %number%
Untested: This expects text in the first line of abc.config which is the file information such as Quest in the example and if there are more than 2 matching files in the source folder then it will echo a move command to move them to the target folder.
Change *%file%* to %file%* in two places if you want to match only the start of the filename.
Remove the echo to actually perform the move commands.
#echo off
set "source=c:\mainfolder"
set "target=d:\target\folder"
set /p "file=" < "abc.config"
for /f %%a in ('dir /b /a-d "%source%\*%file%*" ^|find /i "%file%" 2^>nul^|find /c /v "" ') do set "number=%%a"
if %number% GTR 2 for /f "delims=" %%a in ('dir /b /a-d "%source%\*%file%*" ^|find /i "%file%" ') do (
echo move "%source%\%%a" "%target%"
)
pause

Batch script that makes a numbered menu to view log files

I have recently started to learn how to make batch files. I have a folder that contains bunch of internet related log files. When I run the .cmd file (located in the same folder) I want it to be able to find out how many log files are in the folder and make a numbered menu from it. So lets say there are twenty files in the folder, then the user must be able to select from 1 to 21. 21 will close the batch file. Here is what I have done so far:
#echo off
setlocal enableextensions enabledelayedexpansion
set RawData1=TempData%random%.tmp
set FileCtr=0
:MAIN
dir *.log /b | findstr /i /n ".log" > %RawData1%
for /f "tokens=1 delims=:" %%a in (%RawData1%) do set FileCtr=%%a
set /a ExitCode=%FileCtr% + 1
set UserChoice=%ExitCode%
echo.
echo +++++++++++++++++++++++++++
echo Weblog File Viewer
echo +++++++++++++++++++++++++++
for /f "tokens=1-2 delims=:." %%a in (%RawData1%) do echo %%a. %%b
echo %Exitcode%. To Quit.
set /p UserChoice= Choose item number from menu (%UserChoice%):
echo\
echo user entered: %UserChoice%
pause
:THEEND
del /q %RawData1%
So what this batch file can do for now is that it figures out the number of log files and makes a numbered menu from it. Of course it won't show the filetype which is how I wanted it. So "Kelley-Blue-Book.log" for example is shown only as "Kelley-Blue-Book". However, if the user selects say number 4 from the list the program will terminate because I couldn't figure out how to make it actually open the desired log file using notepad.
This should do what you want:
#echo Off
setlocal EnableDelayedExpansion
set "Count=0"
pushd "%~dp0"
echo.
echo +++++++++++++++++++++++++++
echo Weblog File Viewer
echo +++++++++++++++++++++++++++
for %%A in (*.log) do (
set /a "Count+=1"
set "Menu[!Count!]=%%~fA"
set "Number= !Count!"
echo !Number:~-3!. %%~nA
)
set /a "Count+=1"
set "Number= %Count%"
echo %Number:~-3%. To Quit.
:Prompt
set "UserChoice="
set /p "UserChoice= Choose item number from menu (%Count%):"
if not defined UserChoice goto Prompt
set "UserChoice=%UserChoice:"=%"
if "%UserChoice%"=="%Count%" goto Done
for /f "tokens=1,* delims==" %%A in ('set Menu') do (
if /i "Menu[%UserChoice%]"=="%%~A" (
notepad "%%~fB"
set "UserChoice="
)
)
if defined UserChoice echo Invalid Choice.
goto Prompt
:Done
popd
endlocal
exit /b 0
Let me know if you want any explanations.
#echo off
setlocal enableextensions
set RawData1=TempData%random%.tmp
rem Get numbered list of files
dir /b "*.log" | findstr /i /n ".log" > %RawData1%
rem We could use 0 as exitCode,
rem but to keep original behaviour
rem lets count the number of files
for /F "tokens=*" %%f in ('type %RawData1% ^| find /c /v "" ') do set /A ExitCode=%%f + 1
if %ExitCode%==0 (
echo No log files
goto endProcess
)
rem show menu
for /f "tokens=1-2 delims=:." %%a in (%RawData1%) do echo %%a. %%b
echo %Exitcode%. To Quit.
set UserChoice=%ExitCode%
set /p UserChoice= Choose item number from menu (%UserChoice%):
if "%UserChoice%"=="" goto :EOF
if "%UserChoice%"=="%ExitCode%" goto endProcess
rem Search indicated file in list
set SelectedFile=
for /f "tokens=2 delims=:" %%f in ('findstr /B "%UserChoice%:" %RawData1%') do set SelectedFile=%%f
if "%SelectedFile%"=="" (
echo Incorrect selection
goto endProcess
)
if not exist %SelectedFile% (
echo File deleted
goto endProcess
)
notepad %SelectedFile%
:endProcess
del /q %RawData1%

'findstr' with multiple search results (BATCH)

This is based on my last question's script:, Directory mapout is not working (BATCH)
(For the whole script, click the link. However, you may only click the link if the following snip of code from "directory mapout is not working" does not really make sense to you)
<code>
cd temporary
set odir=%dir%
set /p cdir="DIRECTORY: "
set domap=%cdir%
title SONOROUS FILE SEARCHER: Mapping out...
echo PLEASE WAIT, MAPPING OUT DIRECTORY.
dir %domap% /a-d /b /s > "tempres.rsm"
echo Directory Mapout done
echo -----------------------------
echo DIRECTORY MAPOUT
set dirmapout=<tempres.rsm
echo %dirmapout%
echo -----------------------------
title SONOROUS FILE SEARCHER: Mapout done.
set /p "searchinput=Search Term: "
title SONOROUS FILE SEARCHER (Copyright 2013 by Sonorous)
for /f "delims=" %%a in ('findstr /i /L /c:"%searchinput%" "tempres.rsm" ') do set "found=%%a"
set proin=%found%
echo "%found%"
cd temporary
del "tempres.rsm"
</code>
I want the "for /f" command to output MANY search results from one search term.
Is the code not correctly formatted? Please message / comment on this question.
If you simply want to display the matching lines, then ditch the FOR /F altogether
title SONOROUS FILE SEARCHER (Copyright 2013 by Sonorous)
findstr /i /L /c:"%searchinput%" "tempres.rsm"
cd temporary
del "tempres.rsm"
If you need an "array" of matching lines, then:
:: Define the array of matching lines
set "foundCount=0"
for /f delims^=^ eol^= %%a in ('findstr /i /L /c:"%searchinput%" "tempres.rsm" ') do (
set /a "foundCount+=1"
setlocal enableDelayedExpansion
for %%N in (!foundCount!) do (
endlocal
set "found%%N=%%a"
)
)
:: Display the array values
setlocal enableDelayedExpansion
for /l %%N in (1 1 %foundCount%) do echo match %%N = !found%%N!

Resources