I need to run a program for each line in a file. I am triggering four instances at a time. After four instances, waiting for some time and triggering another one. After wait time batch script is breaking.
Please suggest if I'm doing wrong.
for /F "tokens=*" %%J in ( %JobListFile% ) do (
SET JobName=%%J
echo job name !JobName!
if "!JobName!" equ "" (
echo joblist not found... rerun the script..
REM exit /b
) else (
:waittofinish
for /F "tokens=*" %%a in ( 'tasklist /fi "IMAGENAME eq dsexport.exe" ^| grep -c "dsexport.exe"' ) do ( SET /A CurrInstances=%%a )
echo current instance is !CurrInstances!
echo parallelism set to !NoOfParallelInstances!
if "!CurrInstances!" gtr "!NoOfParallelInstances!" (
echo going to wait
sleep 5
goto waittofinish
echo failed to go wait label...
) else (
echo Exporting job: !JobName! ...............Starting
start /b cmd /C "C:/IBM/9.1/InformationServer/Clients/Classic/dsexport.exe /D=%vDomain% /U=%vuserID% /P=%vpassword% /H=%vServer% %vDSProject% /NODEPENDENTS /JOB=!JobName! %tmppath%\!JobName!.dsx"
echo.
echo.
)
)
)
echo script completed...
exit /b
goto :Label breaks the block context of a code block in parentheses ( ... ); this is also true for for ... do ( ... ) loops and if ... ( ... ) else ( ... ) conditions.
To overcome this, you can put the code portion with goto and :Label into a subroutine, because this hides the block context of the calling code portion from goto, like this:
for /F "usebackq tokens=*" %%J in ( "%JobListFile%" ) do (
SET "JobName=%%J"
echo job name !JobName!
if "!JobName!" equ "" (
echo joblist not found... rerun the script..
REM exit /b
) else (
rem /* The `goto` and `:Label` code fragment has been transferred to a subroutine,
rem which receives the current value of variable `JobName` as an argument: */
call :waittofinish "!JobName!"
)
)
echo script completed...
exit /b
:waittofinish JobName
rem // This subroutine contains the `goto` and `:Label` code fragment so that it does no longer appear inside of a block `( ... )`:
for /F "tokens=*" %%a in ( 'tasklist /fi "IMAGENAME eq dsexport.exe" ^| grep -c "dsexport.exe"' ) do ( SET /A CurrInstances=%%a )
echo current instance is !CurrInstances!
echo parallelism set to !NoOfParallelInstances!
if "!CurrInstances!" gtr "!NoOfParallelInstances!" (
echo going to wait
sleep 5
goto :waittofinish
echo failed to go wait label...
) else (
echo Exporting job: %~1 ...............Starting
rem // Not sure if some arguments should be enclosed in `""` in the next line (but I do not know `dsexport.exe`):
start "" /b cmd /C "C:/IBM/9.1/InformationServer/Clients/Classic/dsexport.exe /D=%vDomain% /U=%vuserID% /P=%vpassword% /H=%vServer% %vDSProject% /NODEPENDENTS /JOB=%~1 %tmppath%\%~1.dsx"
echo.
echo.
)
exit /b
N. B.: I didn't check the logic of your script, because I don't have/know grep.exe or dsexport.exe.
Related
The jhove script will process all files %%a from my %input% directory in a for loop. As far as I know taskkill is only used for killing the .exe files but not one loop pass. Would it be possible for this code to wait 60 seconds then kill the loop pass and go to the next one? So do smth. like that timeout /t 1/nobreak>nul taskkill /F /IM "%%a"
for /f "tokens=*" %%a in ('dir /b /a-d /s %input%\*.*') do (
echo Verarbeite %%~na
CALL jhove -m PDF-hul -h xml -o "%output%\%%~na_!count!.xml" "%%a"
set /a count=count+1
set /a loop3+=1
)
You can of course do something like this:
> nul timeout /T 60 /NOBREAK
taskkill ...
But this will wait for 60 seconds even if the process quits before that time elapses.
I would use a polling loop instead and query via tasklist whether or not the process is still running, and if not, go on with processing the next item. Here is a possible way how to accomplish that (see the comments):
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "_INPUT=." & rem // (path to input directory)
set "_OUTPUT=." & rem // (path to output directory)
set "_MASK=*.*" & rem // (input file name pattern)
set "_SCRIPT=%~dp0jhove.bat" & rem // (script to process input files by)
set "_TITLE=JHOVE" & rem // (base window title of script process)
set "_FROZEN=" & rem // (only terminate frozen processes if not empty)
set /A "_TIMEOUT=60" & rem // (timeout value for process; zero means none)
set /A "COUNT=0"
rem // Resolve output directory:
for %%D in ("%_OUTPUT%") do (
rem // Iterate through all input files:
for /F "delims=" %%F in ('dir /S /B /A:-D "%_INPUT%\%_MASK%"') do (
rem // Process input files in a sub-routine:
call :RUN -m PDF-hul -h xml -o "%%~fD\%%~nF_%%COUNT%%.xml" "%%~F"
set /A "COUNT+=1"
)
)
endlocal
exit /B
:RUN
rem // Build unique window title:
set "WTITLE=%_TITLE%_%RANDOM%"
rem // Build image name from command prompt specification:
for %%I in ("%ComSpec%") do set "IMAGE=%%~nxI"
rem // Run script using unique window title:
start "%WTITLE%" /D "%_INPUT%" "%ComSpec%" /D /S /C ^""%_SCRIPT%" %*^"
rem // Skip polling loop in case timeout is set to zero, thus deactivated:
if %_TIMEOUT% leq 0 goto :END
rem // Set filter according to given configuration:
if defined _FROZEN (set "FILTER=/FI "STATUS ne RUNNING"") else set "FILTER="
rem // Try termination without forcing first:
set "FORCE="
rem // Reset timer:
set /A "TIMER=0"
rem // Reset error flag:
set "ERR=0"
:LOOP
rem // Retrieve PID of running command prompt process with unique window title:
set "PID=0"
for /F "tokens=1* delims=:" %%T in ('
2^> nul tasklist /FI "IMAGENAME eq %IMAGE%" /FI "WINDOWTITLE eq %WTITLE%" ^
/FO LIST /V
') do (
if "%%T"=="PID" for /F %%V in ("%%U") do set "PID=%%V"
if "%%T"=="Status" for /F "tokens=*" %%V in ("%%U") do set "STATUS=%%V"
)
rem // Skip loop if no PID has been found (process might already be finished):
if %PID% equ 0 goto :END
rem // Wait for a second, so this is the polling rate:
> nul timeout /T 1 /NOBREAK
rem // Increment timer:
set /A "TIMER+=1"
rem // Check whether timeout limit is reached, loop if not:
if %TIMER% leq %_TIMEOUT% goto :LOOP
rem /* Loop if process is frozen, if desired (this filter (`/FI`) cannot applied
rem to `taskkill` below, because mismatch would not set the exit code, hence
rem use of conditional operators `&&` and `||` would not work): */
if defined FILTER for /F "tokens=1* delims=:" %%T in ('
2^> nul tasklist /FI "IMAGENAME eq %IMAGE%" /FI "WINDOWTITLE eq %WTITLE%" ^
%FILTER% /FO LIST /V
') do if "%%T"=="INFO" goto :LOOP
rem /* Try to terminate process with found PID (`taskkill` sets the exit code in
rem case filters `/PID` or `/IM` deliver a mismatch, but not for `/FI`): */
> nul 2> nul taskkill /PID %PID% %FORCE% && (
rem // Termination succeeded, so return information message:
echo Successfully terminated process:
call :MSG %*
rem // Set error flag:
set "ERR=1"
) || (
rem // Termination failed:
if not defined FORCE (
rem // Normal termination failed, so try termination forcefully now:
set "FORCE=/F"
goto :LOOP
) else (
rem // Forceful termination failed, so return error message:
>&2 (
echo Failed to terminate process:
call :MSG %*
)
rem // Set error flag:
set "ERR=2"
)
)
:END
rem /* Exit with exit code (`ErrorLevel`) set to `0` if no process had to be
rem terminated, `1` if at least one process had to be terminated, and `2`
rem if at least one process could not be terminated (forcefully): */
exit /B %ERR%
:MSG
rem // Return some process details:
echo PID = %PID%
echo image name = %IMAGE%
echo status = %STATUS%
echo window title= %WTITLE%
echo command line= "%_SCRIPT%" %*
echo/
exit /B
My batch file is silently ending execution on the first loop (for /d "delims= eol=|" %%d in (*.*) do () and I can't tell why.
I'm not calling any other batch files
My subfolder names DO contain spaces, which I tried to handle with "delims= eol=|"
I never see !parent!!folder! echoed and it doesn't pause at the end. What am I doing wrong?
#Echo off
setlocal enabledelayedexpansion
pushd "%~dp0"
set "parent=%~dp0"
echo !parent!
set "destination=\\(test destination folder)\"
rem SET "destination=\\(prod destination folder)\"
set "FileCount=0"
for /d "delims= eol=|" %%d in (*.*) do (
set "folder=%%d"
echo !parent!!folder!
pause
for %%f in ("!parent!!folder!\(file identifying-pattern)*.DAT") do (
echo "File Type 1"
pause
if !FileCount! lss 200 (
set /a !FileCount!+=1
ECHO !FileCount!
ECHO !parent!!folder!%%f
ECHO !destination!%%f
MOVE "%%f" "!destination!"
)
(
for %%f in ("!parent!!folder!\(file identifying-pattern)*.DAT") do (
echo "File Type 2"
pause
if !FileCount! lss 200 (
set /a !FileCount!+=1
ECHO !FileCount!
ECHO !parent!!folder!%%f
ECHO !destination!%%f
MOVE "%%f" "!destination!"
)
)
)
for /d %%d in (*.*) do (
set "folder=%%d"
if not %%d==Archive (
if not %%d==Hold (
dir /b "!folder!"|find /v "">nul && ECHO "!folder! NOT EMPTY"||rmdir "!parent!!folder!"
)
)
)
pause
popd
I've took a guess at what you were doing, trying not to change the structure too much!
You'll need to add your destinations on lines 4 and 5 and your file patterns to lines 8 and 9 as necessary. (Please make sure you do not end your destination paths with back slashes):
#Echo Off
CD /D "%~dp0" 2>Nul || Exit /B
Set "Destination=\\(test destination folder)"
Rem Set "Destination=\\(prod destination folder)"
If Not Exist "%destination%\" Exit /B
Set "Pattern1=(file identifying-pattern)"
Set "Pattern2=(file identifying-pattern)"
Set /A Type1Count=Type2Count=0
SetLocal EnableDelayedExpansion
For /D %%A In (*) Do (
For %%B In ("%%A\%Pattern1%*.dat") Do (
Echo "File Type 1"
Set /A Type1Count +=1
If !Type1Count! Lss 200 (
Echo !Type1Count!. "%CD%\%%A\%%B" --^> "%Destination%\%%B"
If Not Exist "%Destination%\%%B\" MD "%Destination%\%%B"
Move /Y "%%B" "%Destination%\%%B">Nul
)
)
For %%C In ("%%A\%Pattern2%*.dat") Do (
Echo "File Type 2"
Set /A Type2Count +=1
If !Type2Count! Lss 200 (
Echo !Type2Count!. "%CD%\%%B\%%C" --^> "%Destination%\%%C"
If Not Exist "%Destination%\%%C\" MD "%Destination%\%%C"
Move /Y "%%C" "%Destination%\%%C">Nul
)
)
If /I Not "%%A"=="Archive" (
If /I Not "%%A"=="Hold" (
Set "file="
For %%D In (*) Do Set "file=1"
If Defined file (Echo %%A NOT EMPTY) Else RD "%%A" 2>Nul
)
)
)
Pause
If you're happy with it in your test you can Remark line 4 and unRemark line 5.
Using a batch script, I am tying to break out of an inner for loop and land on the outer for loop to carry on the sequence but it returns an error saying:
The syntax of the command is incorrect
It is referring to the my :breakerpoint label. Please advice. Thank you.
for /l %%A in (1, 1, %NumRuns%) do (
echo Doing run %%A of %NumRuns%
for /l %%B in (1, 1, 3) do (
ping 127.0.0.1 -n 2 > NUL
tasklist /FI "IMAGENAME eq Reel.exe" 2>NUL | find /I /N "Reel.exe">NUL
echo innerloop top
echo Error lvl is %ERRORLEVEL%
if NOT "%ERRORLEVEL%"=="0" (
echo innerloop middle
goto:breakerpoint
)
echo innerloop bottom
)
taskkill /F /IM "Reel.exe"
:breakerpoint rem this is error line
)
:end
echo end of run
pause
A goto breaks always the current code block and the current code block is the complete block beginning with the first parenthesis, in your case you leave all nested FOR at once.
To avoid this you need to use sub functions.
for /L %%A in (1, 1, %NumRuns%) do (
echo Doing run %%A of %NumRuns%
call :innerLoop
)
exit /b
:innerLoop
for /L %%B in (1, 1, 10) do (
echo InnerLoop %%B from outerLoop %%A
if %%B == 4 exit /b
)
exit /b
I m just trying to invoke a simple counter.To implement that I wrote the below script but the script is only giving me output as "Checking".
#echo off
echo checking
goto :check
:check
for /L %%a IN (1,1,4) do (
echo %%a
if %%a == 4 (
echo a is 4 now
echo congo
goto:eof
) else (
goto :check
)
a few Problems here:
1) you are missing a closing parantheses (very good visible when Code is properly intended)
2) any goto breaks your block (a block is everything between (and )
3) jumping ahead of your for Loop will start it again, resulting in a endless Loop
4) no Need to goto :eof, as for will end of it's own when the Counter reaches 4
5) no need to goto <a label at the very next line>
This results in the following Code:
#echo off
echo checking
for /L %%a IN (1,1,4) do (
echo %%a
if %%a == 4 (
echo a is 4 now
echo congo
)
)
I have a program to search drives for a specific file. The only problem is is that i wont know what drive it is on. The problem occurs when it searches a drive for a file that isn't there is there a way to go on to the next drive after say like 10 seconds. Heres my code so far
#echo off
setlocal EnableDelayedExpansion
set count=1
for /f "skip=1" %%a in ('wmic logicaldisk get caption') do (
set drive!count!=%%a
set /a count+=1
)
set "gh=!drive1!"
::Change this to do whatever with the variables
set "fh=!drive2!"
set "hh=!drive3!"
set "jh=!drive4!"
For /R %gh%\ %%G IN (*.ut2) do set jk="%%~dpG"
if defined jk (
echo %jk%
) else (
goto next
)
for /r %jk% %%a in (*) do if "%%~nxa"=="CTF-Hydro-16-2k3.ut2" set k=%%~dpnxa
if defined k (
echo %k% found
pause
cls
echo You have it
goto end
) else (
echo Map not found
copy %CD:~0,3%\Unrealmap\CTF-Hydro-16-2k3.ut2 %jk%
goto end
)
:next
For /R %fh%\ %%G IN (*.ut2) do set ht="%%~dpG"
if defined ht (
echo %ht%
) else (
goto there
)
for /r %ht% %%a in (*) do if "%%~nxa"=="CTF-Hydro-16-2k3.ut2" set m=%%~dpnxa
if defined k (
echo %m% found
pause
cls
echo You have it
goto end
) else (
echo Map not found
copy %CD:~0,3%\Unrealmap\CTF-Hydro-16-2k3.ut2 %jk%
goto end
:there
:end
cls
echo done
pause
#echo off
for /f "skip=1" %%D in ('wmic logicaldisk get caption') do (
for /r "%%D\\" %%G IN (*.ut2) do (
echo %%~dpG
if exist "%%~dpGCTF-Hydro-16-2k3.ut2" (
echo Found the map.
goto end
) else (
echo Map not found, copying
copy %CD:~0,3%\Unrealmap\CTF-Hydro-16-2k3.ut2 "%%~dpG"
goto end
)
)
)
:end
pause
Try next approach:
#ECHO OFF >NUL
SETLOCAL enableextensions
set /A "ii=0"
for /f "skip=1" %%D in ('
wmic logicaldisk get caption
') do for /F %%d in ("%%D") do (
echo searching %%d
for /F "delims=" %%G IN ('dir /B /S "%%d\CTF-Hydro-16-2k3.ut2" 2^>nul') do (
set /A "ii+=1"
set "k=%%G"
rem remove 'rem' from next line to discontinue searching
rem goto :testfound
)
TIMEOUT /T 10 /NOBREAK >NUL
)
:testfound
if %ii% EQU 0 (
echo Map not found
) else (
echo Map found %ii% times: last one "%k%"
)
Here the for loops against wmic command are
%%D to retrieve the caption value;
%%d to remove the ending carriage return in the value returned: wmic behaviour: each output line ends with 0x0D0D0A (<CR><CR><LF>) instead of common 0x0D0A (<CR><LF>).
See Dave Benham's WMIC and FOR /F: A fix for the trailing <CR> problem
Another eventuality: parse
wmic datafile where "Extension='ut2' and FileName='CTF-Hydro-16-2k3'" get Name 2>NUL