I need to check for certain processes (its a list of 20ish processes, so wont list them all), and record which ones are running. Then I need to kill them, run some other code, and finally reopen them... The code will only run successfully if all the processes have been ended.
I'd welcome any suggestions, or just someone to explain why my code doesn't work.
What I've been doing, is using tasklist to check for each process, and write the results to a file, then I'm trying to remove the lines of the file where the process is not running (i.e. I get an "INFO:..." message)
I know that I have done something similar before, where I've taken each line of a file one at a time (in a for loop), replaced a string of text within it, and sent the edited line to another file (which is probably not the most efficient way of doing it, but it worked).
For some reason, I can't replicate it now...
The code I've got (whch is failing) is
SETLOCAL ENABLEDELAYEDEXPANSION
cd\
for /f "tokens=* delims= " %%a in (somefile.txt) do (
set q=INFO: No tasks are running which match the specified criteria.
set r=%%a
set s=!r:%q%=!
echo %s% >>test.txt
)
If anyone knows of a better way to do what I need, I'm happy to change my plan, but it does need to be done through batch (CMD), or I'd be happy with some one fixing the above code at least.
Thanks
Try this code. Though I'm not sure if the output file matches the one you want. Make sure to surround the parameter with double quotes if it contains any space.
taskchk.cmd:
#echo off
SETLOCAL ENABLEDELAYEDEXPANSION
if "%1" == "" (
echo Please specify criteria.
echo e.g.: taskchk myprocess.exe
goto :eof
)
cd\
type nul>test.txt
set found=0
for /f "tokens=*" %%a in ('tasklist /nh') do (
for /f "tokens=1" %%b in ("%%a") do (
if /i "%%b" == "%~1" (
set found=1
) else (
echo %%a>>test.txt
)
)
)
if %found% == 0 echo INFO: No tasks are running which match the specified criteria.>>test.txt
Related
I'm trying to read the output of a command (which outputs into multiple lines), and use an arbitrary number of those lines. Because I know neither the number of total lines, nor the number of lines that will be used, I need to analyse and possibly use each line in a loop, which is why I have setlocal enabledelayedexpansion.
Below is a snippet of the code that shows the process of taking the command and reading each line (not using it yet, just reading it to make sure this works (which it doesn't)):
#echo off
setlocal enabledelayedexpansion
for /f "tokens=*" %%i in ('svn status') do (
echo %%i
set file=%%i
echo *!file!
)
The problem that I'm running into is that the %%i values that are being read in are not correct in the for line. The first character is missing from the first line of the input (which is important because I use the first line to decide whether or not to use that line).
The output I get from my code looks like this:
Dir0\TestDoc7.txt
? StatusFile.txt
Whereas if I run this code:
copy /y NUL StatusFile.txt >NUL
>StatusFile.txt (
svn status
)
(Which is just another way of me seeing what the real output of svn status is) I get a proper output into the text file:
! Dir0\TestDoc7.txt
? StatusFile.txt
I'm probably making a fairly clear mistake as I'm rather new to batch scripting.
Thanks in advance.
The cause is EnableDelayedExpansion which will eat the exclamation marks,
Your choice of tokens=* will also strip all leading spaces from the lines.
#echo off
for /f "tokens=1*" %%A in ('svn status') do (
if "%%A" equ "!" (
Rem do whatever
) else If "%%A" equ "?" (
Rem do something else rest of the line is in %%B
) else (
Rem no ! or ? first space sep. content is in %%A rest of the line is in %%B
)
)
I am basically trying to write a script on WIN10 that will allow me to start a python script, monitor for it to complete before moving on the next step. This looks like it should work but it just loops at the 2s timer, even after I close the notepad windows. This is kind of a combination of 2 scripts I found on here so I may be way out to lunch on my methods.
#echo off
set PROCESSNAME=notepad.exe
::First save current pids with the wanted process name
setlocal EnableExtensions EnableDelayedExpansion
set "RETPIDS="
set "OLDPIDS=p"
for /f "TOKENS=1" %%a in ('wmic PROCESS where "Name='%PROCESSNAME%'" get ProcessID ^| findstr [0-9]') do (set "OLDPIDS=!OLDPIDS!%%ap")
::Spawn new process(es)
start %PROCESSNAME%
::Check and find processes missing in the old pid list
for /f "TOKENS=1" %%a in ('wmic PROCESS where "Name='%PROCESSNAME%'" get ProcessID ^| findstr [0-9]') do (
if "!OLDPIDS:p%%ap=zz!"=="%OLDPIDS%" (set "RETPIDS=/PID %%a !RETPIDS!")
)
:check
set stillalive=no
for /f "tokens=2" %%b in ('tasklist') do (
set pid=%%b
if !pid! == %RETPIDS% (
set stillalive=yes
)
)
if %stillalive% == yes (
cls
echo/Oh! He's still there, I'll wait.
timeout /t 2 /nobreak
goto check
) else (
echo/He's not there anymore, start the party!!
)
pause>nul
If there is a simpler way of doing this that's fine, if I can get this working with notepad, it should be easy to adapt to suit my needs.
Thanks in advance.
It's necro, I know, but I looked for something similar and just ended up here. This did a trick and fixed the script:
Replace
(set "RETPIDS=/PID %%a !RETPIDS!")
with
(set "RETPIDS=%%a!RETPIDS!")
The thing is that RETPIDS value looked like /PID 18465 and pid value was like 18465 and there also was a mess up with !!, %%, "%%" stuff and condition therefore strangely triggered every time although it obviously shouldn't.
Also seems that yours RETPIDS implies a possibility of several PIDs in one string like "5147 8463 6521" but it defenitely won't work with your single !pid! comparison in a loop.
I have hundreds of csv files . csv files are stored in folders and sub folders . I want to search fifty csv file whose file names have been determined , for example 1.csv , 2.csv , 3.csv , ... , 50.csv . very troublesome if I searched one by one using the Windows search tool . I would like if the files are found , save in the folder named FOUND . please help to overcome this problem by using the batch programming / bat ? thank you very much
There's a number of approaches one can take, depending on how much automation you require... To help you get started, you may want to look at this it helped me (and indeed continues to do so) when I started learning batch. Furthermore I will provide one possible template for achieving your objective, as I have interpreted it. Perhaps it is not the most elegant or efficient method, but it introduces a number of batch commands that you may or may not have encountered, which in turn may help you develop your own method.
#echo off
setlocal enabledelayedexpansion
echo Please enter a drive letter:
set /p "drive=>"
echo Please enter a search string:
set /p "searchstring=>"
echo %searchstring%>search.txt
set /p search=<search.txt
set /a suffix=0
echo.>>search.txt
:LOOP
for /f "tokens=*" %%i in ("search.txt") do (
set /a suffix=suffix+1
set seq=%search% !suffix!
echo !seq!>>search.txt
)
if !suffix! leq 49 goto LOOP
for /f "tokens=*" %%i in (search.txt) do (
for /f "tokens=*" %%j in ('dir /b /s /a-d %drive%:\"%%i.csv" 2^>nul') do (
if not exist "%~dp0\found" md "%~dp0\found"
move /y "%%j" "%~dp0\found\%%~nxj"
)
)
pause
This is not intended as a definitive solution, though you may find it answers your original query/request. All the best.
Here's another working solution for you..
#ECHO OFF
SETLOCAL EnableDelayedExpansion
REM First Set your directories input and output
SET InputDir=C:\Directory to your CSV files\
SET OutputDir=C:\Directory to your CSV files\FOUND
REM check if the FOUND directory exist, if not, then create it.
IF NOT EXIST OutputDir (
mkdir %OutputDir%
)
REM Grab a scan of the input directory and save it to a temporary file list.
Dir /a /b %InputDir%>"%OutputDir%\Found.txt"
REM Set the files you would like to find.
SET "File1=1.csv"
SET "File2=2.csv"
SET "File3=50.csv"
REM The loop, to process the matching file(s).
FOR %%A IN (%File1%,%File2%,%File3%) DO (
FOR /F "usebackq" %%B IN ("%OutputDir%\Found.txt") DO (
IF %%A==%%B (
copy "%InputDir%\%%A" "%OutputDir%\%%A"
)
)
)
REM Clean up the temp file list.
DEL "%OutputDir%\Found.txt"
Make note, I didn't add quotes to the Input and Output variables, but instead added quotes to the copy portion of the code to compensate for white spaces in your directory path. I tried to keep it simple, so you could follow the logic of how it processed what you are looking for, you can now modify this to your liking.. Have fun. Cheers!
I'm not very familiar with BAT files but I have a file that runs a sqlplus query, returns the row count, and if it is greater than 0, run another bat file. I feel like I'm almost there but I keep getting this error:
%%a was unexpected at this time
#echo off
for /f "delims=" %%a in (
'sqlplus USER/PASS#OMP1 #VoiceBlockTrig.SQL'
) do set rowcount=%%a
if %ROWCOUNT% GTR 0 (
c:\SQLTRIGGERS\VoiceBlkAutoationBAT.bat
)
when I run the above, I get this as a reponse:
#echo off
for /f "delims=" %%a in (
%%a was unexpected at this time
'sqlplus USER/PASS#OMP1 #VoiceBlockTrig.SQL'
''sqlplus' is not recognized as an internal or external command, operable program or batch file
) do set rowcount=%%a
if %ROWCOUNT% GTR 0 (
More? c:\SQLTRIGGERS\VoiceBlkAutoationBAT.bat
More?
when I run this:
sqlplus user/pass#P1 #VoiceBlockTrig.SQL
I do get an integer value back too
why is there such a gap between the SET and rowcount?
In itself, it's of no matter - but I suspect that you have them on separate lines.
The set rowcount=%%a must all be on the same physical line as the do - and the do must be on the same physical line as the closing parenthesis after the in
for /f "delims=" %%a in (
'sqlplus user/pass#P1 #VoiceBlockTrig.SQL'
) do set rowcount=%%a
if perfectly legitimate.
As a .bat file:
:: #echo off
echo starting SQLPLUS
sqlplus USER/PASS#OMP1 #VoiceBlockTrig.SQL
echo finished SQLPLUS
for /f "delims=" %%a in (
'sqlplus USER/PASS#OMP1 #VoiceBlockTrig.SQL'
) do ECHO(+%%a+&set /A rowcount=%%a
ECHO rowcount=+%rowcount%+
if %ROWCOUNT% GTR 0 (
c:\SQLTRIGGERS\VoiceBlkAutoationBAT.bat
)
PAUSE
This is the batch that appears to be close to what you'd need to run.
The changes are:
added ECHO(+%%a+ in the FOR loop.
The open-parenthesis following the ECHO is simply a character that has been found to be better than SPACE to separate the ECHO from the text-to-be-echoed
The + before and after the %%a simply delimits the string with an
obvious character so that the presence of SPACES can be more easily observed.
SET changed to SET /A which interprets the value assigned as a
numeric-string, which should overcome any stray spaces in the
assignment.
Added ECHO of the rowcount within delimiters for visibility
Added PAUSE to stop the procedure from closing before you have a chance to see the results.
Comment : Probably the "delims=" is not required, but we'll get to that when the problems are defeated.
Comment: Your report that the script required TWO ENTERs could mean that the SQLPLUS is asking for input. If so, 'ECHO.^|sqlplus... may alleviate the problem.
If SQLPLUS is a BATCH, a different approach would need to be made.
Further changes to attempt to solve puzzing result:
Double-colon before #echo off - double-colon is often used as a
comment. The object is to show the lines being executed.
Added the SQLPLUS command independently - to observe results.
Added two ECHO lines to display progress.
Certainly very odd....
I am creating an MS DOS batch script that needs to list every .bat file in the current directory, but not show autoexec.bat or other utilities or systems .bat files that shouldn't be run by the user.
I currently have DIR "*.bat" /B /P
This lists all .bat files appropriately, but it shows autoexec.bat. How would I exclude that from the list? Also slightly important, how could I chop off the file extensions and show more than the 7-characters DOS limits files to?
Constraints: I am not able to use a DOS version above WinME. That is the version I am using.
Thanks for any help.
EDIT:
There is plenty of information on the internet about doing this, but it is all in the windows command processor, not MS DOS. Please understand that DOS and the Command Prompt are not the same thing.
#echo off
setlocal EnableDelayedExpansion
rem Add more names separated with slashes here:
set exclude=/autoexec/
for %%a in (*.bat) do (
if "!exclude:/%%~Na/=!" equ "%exclude%" (
echo %%~Na
)
)
EDIT: Some explanations added
Batch file processing is slow, so you should use techniques that allows a Batch file to run faster. For example:
Try to use the minimum lines/commands to achieve a certain result. Try to avoid external commands (*.exe files) like find, findstr, fc, etc. specially if they work on small amounts of data; use if command instead.
Use for %%a in (*.bat)... instead of for /F %%a in ('dir /B *.bat').... The second method requires to execute cmd.exe and store its output in a file before for command can process its lines.
Avoid pipes and use redirections instead. A pipe require the execution of two copies of cmd.exe to process the command at each side of the pipe.
A simple way to check if a variable contain a given string is trying to delete the string from the variable: if the result is different then the string exists in the variable: if "!variable:%string%=!" neq "%variable%" echo The string is in the variable.
Previous method may also be used to check if a variable have anyone of a list of values: set list=one two three, if "!list:%variable%=!" neq "%list%" echo The variable have one value from the list. If the values of the list may have spaces, they must be separated by another delimiter.
EDIT: New version added as answer to new comments
The easiest way to pause one page at a time is to use more filter this way:
theBatchFile | more
However, the program must reorder the output in order to show it in columns. The new version below achieve both things, so it does not require more filter; you just need to set the desired number of columns and rows per page.
#echo off
setlocal EnableDelayedExpansion
rem Add more names separated with slashes here:
set exclude=/autoexec/
rem Set the first two next variables as desired:
set /A columns=5, rows=41, wide=(80-columns)/columns, col=0, row=0
rem Create filling spaces to align columns
set spaces=
for /L %%a in (1,1,%wide%) do set spaces= !spaces!
set line=
for %%a in (*.bat) do (
if "!exclude:/%%~Na/=!" equ "%exclude%" (
rem If this column is less than the limit...
set /A col+=1
if !col! lss %columns% (
rem ... add it to current line
set name=%%~Na%spaces%
set "line=!line!!name:~0,%wide%! "
) else (
rem ... show current line and reset it
set name=%%~Na
echo !line!!name:~0,%wide%!
set line=
set /a col=0, row+=1
rem If this row is equal to the limit...
if !row! equ %rows% (
rem ...do a pause and reset row
pause
set row=0
)
)
)
)
rem Show last line, if any
if defined line echo %line%
Antonio
attrib +h autoexec.bat
should hide autoexec.bat and it should thus not appear in the list
DIR "*.bat" /B /P | find /v "autoexec" | for %i in (*.bat) do #echo %~ni
Using for to process each file name individually:
setlocal enabledelayedexpansion
for /f %%i in ('dir "*.bat" /b') do (
set system=0
if "%%i"=="autoexec.bat" set system=1
if "%%i"=="somesystem.bat" set system=1
if !system!==0 echo %%i
)
Another method without variables:
for /f %%i in ('dir "*.bat" /b') do call :test %%i
goto continue
:test
if "%1"=="autoexec.bat" goto :eof
if "%1"=="somesystem.bat" goto :eof
echo %1
goto :eof
:continue
For both, you can add new filenames to exclude from the list.