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%
Related
So what I'm trying to do is, i have a bat file that makes timestamped backups(for example, 180126_053327 in the format: yymmdd_hhmmss). I'm trying to create this bat to add to it, so i can have it lookup those backups, display in console to allow the user to select the backup they want to restore by inputting the number they want and then copy it to a location.
so far what i have creates this:
Pic of what I have so far
The pic above is from the following script:
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
set i=0
For /f %%a in ('dir I:\AM_Configs-backups\ /B /A /D') do (
set /a i+=1
echo !i! %%a
set dir!i!=%%a
)
echo.
set /p uin="Select a directory [1-!i!]: "
set udir=!dir%uin%!
echo Selected - %udir%
md c:\test2
copy %udir% c:\test2
#PAUSE
I keep getting this:
Select a directory [1-29]: 27
Selected - 180126_053327
The system cannot find the file specified.
Press any key to continue . . .
I got the script above from this link: Prompting user to select directory in batch file
It cannot be found because %udir% is not in the current directory. This means that your base directory, I:\AM_Configs-backups, needs to be pre-fixed to your Copy command.
Copy "I:\AM_Configs-backups\%udir%" "C:\test2"
Also here is an alternative to the linked example you provided in your question:
#Echo Off
SetLocal EnableDelayedExpansion
Set "baseDir=I:\AM_Configs-backups"
For /F "Delims==" %%A In ('"(Set dir[) 2>Nul"') Do Set "%%A="
Set "i=0"
For /D %%A In ("%baseDir%\*") Do (Set /A i+=1 & Set "dir[!i!]=%%~nxA")
If %i% Equ 1 (Set "dir[X]=%baseDir%\%dir[1]%") Else Call :Menu
Rem Your commands using the selected directory begin below
Echo you selected %dir[X]%
If Not Exist "C:\test2\" MD "C:\test2"
Copy "%dir[X]%" "C:\test2"
Pause
Exit /B
:Menu
For /L %%A In (1,1,%i%) Do (Echo %%A. !dir[%%A]!)
Set /P "dir[X]=Select a directory from the above list: "
If Not Defined dir[%dir[X]%] (ClS & GoTo Menu)
Set "dir[X]=%baseDir%\!dir[%dir[X]%]!"
You can adjust your base directory on line 3 and put your own commands from line 9 onwards, (up to the Exit /B).
You should consider using RoboCopy for copying directories!
Edit
For the XCopy version, you'd probably need to change to:
#Echo Off
SetLocal EnableDelayedExpansion
Set "baseDir=I:\AM_Configs-backups"
For /F "Delims==" %%A In ('"(Set dir[) 2>Nul"') Do Set "%%A="
Set "i=0"
For /D %%A In ("%baseDir%\*") Do (Set /A i+=1 & Set "dir[!i!]=%%~nxA")
If %i% Equ 1 (Set "dir[X]=%dir[1]%") Else Call :Menu
Rem Your commands using the selected directory begin below
Echo you selected %dir[X]%
XCopy "%baseDir%\%dir[X]%" "%AppData%\Awesomeminer\%dir[X]%" /S /I /F /Y 2>Nul
Echo Starting Awesome Miner...
Start "" "%ProgramFiles(x86)%\Awesome Miner\AwesomeMiner.exe"
Pause
Call "Switch-N-Bkup.bat"
Pause
Exit /B
:Menu
For /L %%A In (1,1,%i%) Do (Echo %%A. !dir[%%A]!)
Set /P "dir[X]=Select a directory from the above list: "
If Not Defined dir[%dir[X]%] (ClS & GoTo Menu)
Set "dir[X]=!dir[%dir[X]%]!"
For the RoboCopy version you'd change line 11 to:
RoboCopy "%baseDir%\%dir[X]%" "C:\test2\%dir[X]%" /S 2>Nul
...plus any additional switches you may need
I ended up using this cus i have another batch for switching and backing up:
to kinda give you an idea, i have a primary bat for switching and copying configs, which will start teh program automatically after their copied. in that bat i also have code for backing up current configs to a location using time/date and creates the folders in this format: yymmdd_hhmmss...i needed an easy restore function, which with the link and code you provided helped with the user able to select which folder to restore and copying it to the programs data folder to be used, then auto-starting the program using the copied config.
#Echo Off
SetLocal EnableDelayedExpansion
Set "baseDir=I:\AM_Configs-backups"
For /F "Delims==" %%A In ('"(Set dir[) 2>Nul"') Do Set "%%A="
Set "i=0"
For /D %%A In ("%baseDir%\*") Do (Set /A i+=1 & Set "dir[!i!]=%%~nxA")
If %i% Equ 1 (Set "dir[X]=%baseDir%\%dir[1]%") Else Call :Menu
Rem Your commands using the selected directory begin below
Echo you selected %dir[X]%
REM If Not Exist "C:\test2\" MD "C:\test2"
xcopy "%dir[X]%" "%USERPROFILE%\AppData\Roaming\Awesomeminer\" /S /F /R /Y
START C:\"Program Files (x86)"\"Awesome Miner"\AwesomeMiner.exe
ECHO Starting Awesome Miner...
#Pause
CALL Switch-N-Bkup.bat
exit /b
:Menu
For /L %%A In (1,1,%i%) Do (Echo %%A. !dir[%%A]!)
Set /P "dir[X]=Select a directory from the above list: "
If Not Defined dir[%dir[X]%] (ClS & GoTo Menu)
Set "dir[X]=%baseDir%\!dir[%dir[X]%]!"
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.
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!
In the source file I have:
...
<!-- MARK_BEGIN -->
some text line 1
some text line 2
...
<!-- MARK_END -->
...
that I want to copy the above marked content, without the begin/end marks, into a destination file, either at the very beginning, the very end, or at a location marked as:
...
<!-- INSERT_HERE -->
...
The command would be:
copyMarkedContent.bat sourceFile destFile [TOP | BOTTOM | MARKED ]
The sourceFile is guaranteed to have the lines containing MARK_BEGIN and MARK_END in them. The destFile is guaranteed to have the line containing INSERT_HERE if the MARKED argument is given to the copyMarkedConent.bat command.
Is there a way to do this with a .bat script on Windows (Windows 7 or Windows 2008) using just those facilities that come with the OS?
I haven't tested this, but I think it'll do what you are looking for. If there's an error in it, at least it'll get you started.
#echo off
setlocal enabledelayedexpansion
if #%3==# goto usage
:: convert %3 to upper case
for /f "tokens=5" %%I in ('find "" "%3" 2^>^&1') do set arg=%%I
for %%I in (TOP BOTTOM MARKED) do (if "%arg%"=="%%I" goto next)
:usage
echo usage: %~nx0 sourceFile destFile [TOP^|BOTTOM^|MARKED]
goto :EOF
:next
set /p I="Scraping data from %1... "<NUL
set tempfile=~%time::=%.txt
set tempfile=%tempfile: =%
set tag=0
for /f "tokens=1,2* delims=:" %%H in ('findstr /n ".*" %1') do (
if not "%%J"=="" (set line=%%I:%%J) else (set line=%%I)
if !tag!==1 (
for /f "tokens=*" %%x in ('echo "!line!" ^| find /i "<!-- mark"') do (
echo Done.
goto %arg%
)
if "!line!"=="" (echo;>>%tempfile%) else (echo !line!>>%tempfile%)
)
for /f "tokens=*" %%x in ('echo "!line!" ^| find /i "<!-- mark"') do set tag=1
)
:TOP
set /p I="Prepending data to %2... "<NUL
type %2>>%tempfile%
move /y %tempfile% %2 >NUL
echo Done.
goto :EOF
:BOTTOM
set /p I="Appending data to %2... "<NUL
type %tempfile%>>%2
del /q %tempfile%
echo Done.
goto :EOF
:MARKED
set /p I="Inserting data into %2... "<NUL
set tag=0
set tempfile2=~%time::=%_2.txt
set tempfile2=%tempfile2: =%
for /f "tokens=1,2* delims=:" %%H in ('findstr /n ".*" %2') do (
if not "%%J"=="" (set line=%%I:%%J) else (set line=%%I)
if "!line!"=="" (echo;>>%tempfile2%) else (echo !line!>>%tempfile2%)
if !tag!==0 (
for /f "tokens=*" %%x in ('echo "!line!" ^| find /i "<!-- insert"') do (
set tag=1
type %tempfile%>>%tempfile2%
del /q %tempfile%
)
)
)
move /y %tempfile2% %2 >NUL
echo Done.
EDIT 1 : I made the checks for <!-- MARK and <!-- INSERT case insensitive and not dependent on having no spaces before.
EDIT 2 : I broke down and actually started testing my changes. I made a few changes to ensure that indentation and other formatting gets preserved, and the script tests successfully on my Win 7 machine.
I cant seem to get this to work. I need a batch file to go through a bunch of folders with files in them and move them to folders specified in the list .txt.
Basically I want it to do the following:
sample list.txt
folder1 file1
folder2 file1
and parse that so that i can:
copy C:\folder1\file1*.txt to destination folder
copy C:\folder2\file1*.txt to destination folder
etc
Here is what I have so far:
Main program:
echo off
set lines=0
for /f "tokens=1 delims=" %%a in (%CD%\list.txt) do (
echo %%a
echo 1 %SN% from EEN %EEN%
call :first %%a
echo 2 %SN% from EEN %EEN%
call :second %%a
echo 3 %SN% from EEN %EEN%
set /a lines+=1
)
echo %lines%
pause
goto :eof
:first
set EEN=%1
goto :eof
:second
set SN=%2
goto :eof
pause
list.txt (first column is folder name, second is file name):
DM5V37H WMC1F0077774
DM5V37H WMC1F0077711
DM5V37H WMC1F0086480
DM5V37H WMC1F0086372
DM5V37H WMC1F0077655
DM5V37H WMC1F0077770
What am I doing wrong?
I'm not sure about your references to SN and EEN, but I just tested this and it seems to work. The first section is a demonstration of how to access each item in a line read from the file, then the actual move operation is performed. I'm sure you can modify it to your needs.
#echo off
set lines=0
for /f "tokens=1,2 delims= " %%a in (list.txt) do echo %%a %%b&set /a lines+=1
echo Number of lines: %lines%
:: Perform move operation.
for /f "tokens=1,2 delims= " %%a in (list.txt) do (
if not exist %%a (md %%a)
move "%%b" "%%a\%%b"
)