Multithreaded batch file passing parameters - windows

The multithreading part was already replied here and works great (thanks a lot to Magoo)
Main code
SET /a instances=%NUMBER_OF_PROCESSORS%
:: make a tempfile
:maketemp
SET "tempfile=%temp%\%random%"
IF EXIST "%tempfile%?" (GOTO maketemp) ELSE (ECHO.>"%tempfile%a")
::
:loop
SET "nextfile=%~1"
IF NOT DEFINED nextfile (
DEL "%tempfile%a*" >NUL 2>NUL
::ECHO all done
exit
)
FOR /L %%a IN (1,1,%instances%) DO (
IF NOT EXIST "%tempfile%a%%a" (
>"%tempfile%a%%a" ECHO.
START /B "Instance %%a" oneconversion.bat "%~1" "%tempfile%a%%a" %%a
SHIFT
GOTO loop
)
)
timeout /t 1 >NUL
GOTO loop
Code example of oneconversion.bat
#ECHO OFF
SETLOCAL
CALL truepng.exe "%1"
CALL pngwolf.exe "%1"
DEL "%~2" >NUL 2>NUL
cls
exit
This works up to now.
But when I reserve first 10 parameters in use of commands.How I reserve commands
FOR /f "TOKENS=1-11*" %%a in ("%*") DO (
SET filelist=%%l
)
SET varresize=%1
SHIFT
SET varincsmall=%1
SET varwidth=%2
SET varheight=%3
SET varjpegqa=%4
SET varjpegpr=%5
SET varjpegex=%6
SET varpngqa=%7
SET varpngcl=%8
SET varpngqt=%9
I don't know how can I use %filelist% inside main code. And sure replacing %~1 with %filelist% doesn't work. Looks like I missed a point and couldn't find a way out.
Thanks for everyone will help or at least try to.

Add your variable initialization code at the start of the main script and shift the command line parameters additionally 9 times:
SET varresize=%1
SHIFT
SET varincsmall=%1
SET varwidth=%2
SET varheight=%3
SET varjpegqa=%4
SET varjpegpr=%5
SET varjpegex=%6
SET varpngqa=%7
SET varpngcl=%8
SET varpngqt=%9
for /L %%a in (1,1,9) do shift
Thus you won't need filelist, I think.

Related

Aligning output from batch file For loop

REM ************************ HIGH SCORES TABLE
**********************************************
:highscorestable
set /a count = 0
for /f "tokens=1,2,3 delims=-" %%i in (highscores.txt) do (
set hs=%%i
set hsn=%%j
set hsv=%%k
set hst=%%jscored %%iusing%%k
set hsn1=!hsn!
set hsv1=!hsv!
set hs1=!hs!
set hsn1= %hsn1%
set hsv1= %hsv1%
set hs1= %hs1%
echo %hsn1:~-15% %hsv1:~-15% %hs1:~-15%
set /a count+=1
if "!count!"=="5" goto :end
)
:end
echo.
pause
I'm pulling the first 5 lines from a text file using a For loop. My variables populate fine, however I'm struggling with the required alignment.
My ultimate end result should be:
James Commitment 300
Markos Excellence 290
Jeremy Si Party 50
What obvious thing am I missing here?
You could try this:
SetLocal EnableDelayedExpansion
REM **************************** HIGH SCORES TABLE ****************************
:highscorestable
Set "count=0"
For /F "UseBackQTokens=1-3Delims=-" %%i In ("highscores.txt") Do (
Set "hs=%%i"
Set "hsn=%%j"
Set "hsv=%%k"
Set "hst=%%jscored %%iusing%%k"
Set "hs= %%i "
Set "hsn1=%%j "
Set "hsv1=%%k "
Echo !hsn1:~,15!!hsv1:~,15!!hs:~-15!
Set/A count+=1
If "!count!"=="5" GoTo :end
)
:end
Echo(
Pause
Or without the possibly unnecessary variables:
SetLocal EnableDelayedExpansion
REM **************************** HIGH SCORES TABLE ****************************
:highscorestable
Set "count=0"
For /F "UseBackQTokens=1-3Delims=-" %%i In ("highscores.txt") Do (
Set "hs= %%i "
Set "hsn=%%j "
Set "hsv=%%k "
Set "hst=%%jscored %%iusing%%k"
Echo !hsn:~,15!!hsv:~,15!!hs:~-15!
Set/A count+=1
If "!count!"=="5" GoTo :end
)
:end
Echo(
Pause
In both cases, I've added the necessary SetLocal EnableDelayedExpansion line just in case it isn't in your script prior to your provided code.
Edit
You can also alter the code a little forego delayed expansion: (my preferred option)
REM **************************** HIGH SCORES TABLE ****************************
:highscorestable
For /F "Tokens=1-4Delims=:-" %%A In ('FindStr/N $ "highscores.txt"'
) Do If %%A LEq 5 (Set "hst=%%Cscored %%Busing%%D"
Set "hss= %%B"
Set "hsn=%%C "
Set "hsv=%%D "
Call Echo %%hsn:~,15%%%%hsv:~,15%%%%hss:~-10%%)
Echo(
Pause
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET "sourcedir=U:\sourcedir"
SET "filename1=%sourcedir%\q46747991.txt"
REM ************************ HIGH SCORES TABLE
REM **********************************************
:highscorestable
set /a count = 0
SET "manyspaces= "
for /f "tokens=1,2,3 delims=-" %%i in (%filename1%) do (
set hs=%%k&CALL :align hs -8
set hsn=%%i&CALL :align hsn 15
set hsv=%%j&CALL :align hsv 10
ECHO !hsn!!hsv!!hs!
set /a count+=1
if "!count!"=="5" goto end
)
:end
echo.
GOTO :EOF
:align
IF %2 gtr 0 (
CALL SET "%1=%%%1%%%manyspaces%"
CALL SET "%1=%%%1:~0,%2%%"
) ELSE (
CALL SET "%1=%manyspaces%%%%1%%"
CALL SET "%1=%%%1:~%2%%"
)
GOTO :eof
I edited your results for a source file which I named to suit my system, hence the sequence of coulmns is different from your unpublished source. I changed the metavariable-assignment to suit.
The :align routine peels potatoes by recognising the second argument as the required column-width, positive for left-align and negative for right-align.
The variable manyspaces is set to an obvious value, of sufficient length to cope with the widest column required. Obviously, since it won't change once established, it's best set in the very beginning of the batch.
The routine uses the call set %%var%% method so that it will work regardless of whether delayedexpansion is invoked or not.
The mechanics are, for instance
CALL SET "%1=%%%1%%%manyspaces%"
with %1=fred
First, parse the command. %1 is replaced by fred and %% by %, yielding
set
"fred=
%fred%[spaces]"
So appends the space-string to the current value of the environment variable specified as %1
The second set - analyse similarly; result is assigned to the environment variable specified as %1
So the routine can be used to generate a fixed-width string, appropriately aligned using any ordinary variable, even if the variable has a value of nothing (ie. is undefined)

Batch check and replace string then wait for a process

I need a batch file witch will:
check inside user.cfg file for string "g_language = Russian" and leave it if
finds it but if sting is set to "g_language = English" then set it to
"g_language = Russian"
wait for some.exe to start and when it is started
change string "g_language = Russian" to "g_language = English"
How can I do this?
I used this code but my result is:
Russian=g_language = English= Russian
#echo off &setlocal
set "search=g_language = Russian"
set "replace=g_language = English"
set "textfile=user.cfg"
set "newfile=user.bak"
(for /f "delims=" %%i in (%textfile%) do (
set "line=%%i"
setlocal enabledelayedexpansion
set "line=!line:%search%=%replace%!"
echo(!line!
endlocal
))>"%newfile%"
del %textfile%
rename %newfile% %textfile%`
#echo off &setlocal
set "Russian=g_language = Russian"
set "English=g_language = English"
set "textfile=user.cfg"
set "newfile=user.bak"
Call :SwapLang Russian
Start "" some.exe
Timeout /t 5
Call :SwapLang English
Goto :Eof
:SwapLang %1 byRef
( for /f "delims=" %%i in (%textfile%) do (
set "line=%%i"
setlocal EnableDelayedExpansion
If /I "!line:~0,12!" Equ "g_language =" (
echo(!%1!
) Else (
echo(!line!
)
endlocal
)) > "%newfile%"
del %textfile%
rename %newfile% %textfile%
Goto :Eof
Heres an alternative to the great answer already given.
I haven't been able to test this, (please try it in a test environment first), and only do so if you feel you would benefit from the slightly different approach.
#Echo Off
Set "fexe=some.exe"
Set "fcfg=user.cfg"
Set "fbak=user.bak"
Set "sstr=g_language"
Set "rlng=Russian"
Set "elng=English"
If Exist "%fbak%" (If Not Exist "%fcfg%" (Copy "%fbak%" "%fcfg%"
) Else Copy "%fcfg%" "%fbak%") Else If Exist "%fcfg%" (Copy "%fcfg%" "%fbak%"
) Else Exit/B
QProcess "%fexe%">Nul 2>&1 &&(FindStr/IC:"%sstr% = %elng%" "%fbak%">Nul||(
Call :Sub "%rlng%" "%elng%"))||(
FindStr/IC:"%sstr% = %rlng%" "%fbak%">Nul||(Call :Sub "%elng%" "%rlng%"
Start "" "%fexe%"))
Exit/B
:Sub
(For /F Delims^= %%A In ('FindStr $ "%fbak%"') Do If /I "%%A"=="%sstr% = %~1" (
Echo %sstr% = %~2) Else Echo %%A)>"%fcfg%"
I have made it so that you should only need to check/adjust the items on lines 3 to 8.
The general idea:
If neither user.cfg and user.bak exist, exit.
If only one of user.cfg or user.bak exists copy one to the other.
If both user.cfg and user.bak exist, copy user.cfg to user.bak.
If some.exe is running and user.cfg's g_language is not English change it to English.
If some.exe is not running and user.cfg's g_language is not Russian change it to Russian and run some.exe.
Of course none of this matters if user.cfg changes do not take effect until some.exe is restarted.

My .bat file won't give a proper output and it stops after reading the first input

I've tried a few things but I can't seem to get my .bat file to give proper output and read past the first line of the input. Any help would be greatly appreciated. I am trying to create this for mass account creation in Active Directory.
#echo off
echo ---- >C:\NewUserCreation\createdusers.txt
setlocal
FOR /F "eol=; tokens=1-12* delims=~" %%i in (C:\NewUserCreation\newusers.txt) do (
set "_lastname=%%i"
set "_firsname=%%j"
set _QWERTY=%%k
call set _midinit=%%_QWERTY:~0,2%%
set _edipi=%%l
set _ptc=%%m
set _ranktitle=%%n
set _subcomponent=%%o
set _unit=%%p
set _position=%%q
set _email=%%r
set _descr=%%s
call :do_user
)
endlocal
notepad C:\NewUserCreation\createdusers.txt
goto :EOF
:do_user
if "%_midinit%"=="%_edipi%" goto :no_middlename
set _samacctname1=%_firsname%.%_midinit%.%_lastname%
set _userPrincipalName=%_edipi%
call :find_existing_user
call set _samacctname=%_samaccountname%
call set _lastinit=%%_lastname:~0,1%%
C:\NewUserCreation\admod -h mydomaincontroller -add -b "cn=%_lastname%\, %_firsname% %_midinit%,ou=NewUsers,ou=n,ou=n,dc=n,dc=n,dc=n,dc=n" objectclass::user "sn::%_lastname%" "givenname::%_firsname%" "initials::%_midinit%" "personaltitle::%_ranktitle%" "company::%_subcomponent%" "department::%_unit%" "PhysicalDeliveryOfficeName::%_position%" "title::%_position%" "employeetype::%_ptc%" "displayname::%_descr%" "description::%_descr%" "samaccountname::%_samacctname%" "st::Anywhere,US" "streetAddress::%_unit%" "postalCode::36805" "countryCode::111" "c::USA" "co::United States" "l::Corporation" "telephoneNumber::DSN 318-872-XXXX" "userPrincipalName::%_edipi%#domain" "userPassword::password"
if /I %ERRORLEVEL% EQU 0 (
set _resultcode=Success
if /I %_samnametest% EQU 274 (call set _resultcode=%%_resultcode%%-DUP)
) ELSE set _resultcode=-ERROR-
#echo on
sleep 15
net user %_samacctname% /DOMAIN /passwordreq:yes
C:\Windows\System32\dsquery * "ou=n,ou=n,dc=n,dc=n,dc=n,dc=n" -filter "(&(objectclass=user)(samaccountname=%_samacctname%))" -s mydomain |exchmbx -me SMTP:%_email%"
#echo off
echo %_resultcode%. . . %_samacctname% Contact: SMTP:%_email% >>C:\NewUserCreation\createdusers.txt
goto :EOF
:find_existing_userz
set _search4Name=%_samacctnamez%
call set _samNameSearchz=%%_search4Name:~0,20%%
call set _samNameSearchzv=%%_search4Name:~0,16%%274
C:\Windows\System32\dsquery * "ou=n,ou=n,dc=n,dc=n,dc=n,dc=n" -filter "(&(&(samaccountname=%_search4Name%)(ObjectClass=User))(!objectClass=computer))" -attr samaccountname|find /I "%_samNameSearchz%" >"%_samNameSearchz%.tmp"
call :samnamefilesizez %_samNameSearchz%.tmp _samNameSearchsizez
del %_samNameSearchz%.tmp
if /I %_samNameSearchsizez% LEQ 1 (set _samaccountnamez=%_samNameSearchz%) ELSE (
set _samaccountnamez=%_samNameSearchzv%
set _lastnamez=%_lastnamez%274
)
echo resulting_sam_account_name %_samaccountnamez%
call set _samnametestz=%_samaccountnamez:~-3%
goto :EOF
:find_existing_user
set _search4Name=%_samacctname1%
call set _samNameSearch=%%_search4Name:~0,20%%
call set _samNameSearchv=%%_search4Name:~0,16%%274
C:\Windows\System32\dsquery * "ou=n,ou=n,dc=n,dc=n,dc=n,dc=n" -filter "(&(&(samaccountname=%_samNameSearch%)(ObjectClass=User))(!objectClass=computer))" -attr samaccountname|find /I "%_samNameSearch%" >%_samNameSearch%.tmp
call :samnamefilesize %_samNameSearch%.tmp _samNameSearchsize
del %_samNameSearch%.tmp
if /I %_samNameSearchsize% LEQ 1 (set _samaccountname=%_samNameSearch%) ELSE (
set _samaccountname=%_samNameSearchv%
set _lastname=%_lastname%274
)
echo resulting_sam_account_name %_samaccountname%
call set _samnametest=%_samaccountname:~-3%
goto :EOF
:samnamefilesize
set %2=%~z1
goto :EOF
:samnamefilesizez
set %2=%~z1
goto :EOF
pause
I would suggest that you are calling :do_user, and that is going to :no_middlename. I can only guess that there is nothing at :no_middlename returning it to the call within your original for loop.

Windows Batch File can't use variable in for syntax

I want to use a variable skip parameter in for loop, but it won't let me do it.
Here is my code
#echo off
setlocal ENABLEDELAYEDEXPANSION
set /p testcase=<testcases.txt
set /a end=%testcase%*13
for /L %%P IN (1,13,%end%) DO (
set skip=skip=%%P
echo !skip!
set vidx=0
for /f "%skip%" %%A in (testcases.txt) do (
set /a vidx=!vidx! + 1
set var!vidx!=%%A
)
)
Here skip is skip=1, but it doesn't skip any line. When I replace it with skip=1. then it works fine, but I want to skip variable no. of lines in each iteration. Please help.
I think with this logic the only option is a subroutine:
#echo off
setlocal ENABLEDELAYEDEXPANSION
set /p testcase=<testcases.txt
set /a end=%testcase%*13
for /L %%P IN (1,13,%end%) DO (
set skip=skip=%%P
echo !skip!
set vidx=0
call :innerFor %%P
)
exit /b 0
:innerFor
for /f "skip=%~1" %%A in (testcases.txt) do (
set /a vidx=!vidx! + 1
set var!vidx!=%%A
)
exit /b 0
parametrization of FOR /F options is a little bit tricky..
Though I have no the content of your files I cant test if this works correctly .

Batch encoding text files

I have this code to read a text file.
#ECHO OFF
SetLocal EnableDelayedExpansion
for /f "delims=" %%x in ('type text.txt') do (
set "Var=%%x"
ECHO !Var!
)
pause
My question is that if i could advance every char in the file by 20 places like "a" would be "t". it can have numbers and symbols too. the txt file is 400 line long and there is between 1 and 120 char per line. does any one know how i could do this.
Sorry, this will not handle all the posibilities, but
#echo off
setlocal enableextensions disabledelayedexpansion
call :setTables
set "inputFile=inputFile.txt"
for /f "usebackq delims=*" %%a in ("%inputFile%") do (
set "data=%%a"
call :handleProblems
set "out="
setlocal enabledelayedexpansion
for /f "delims=" %%b in ('cmd /v:off /q /u /c "echo(!data!"^|more') do (
if defined "%%b" (
set "out=!out!!"%%b"!"
) else (
set "out=!out!%%b"
)
)
echo(!out!
endlocal
)
exit /b
:handleProblems
set "data=%data:!=~%"
set "data=%data:<=^<%"
set "data=%data:>=^>%"
set "data=%data:&=^&%"
set "data=%data:|=^|%"
set "data=%data:)=^)%"
exit /b
:setTables
set ""a"=t"
set ""b"=u"
set ""c"=v"
set ""d"=w"
set ""e"=x"
set ""f"=y"
set ""g"=z"
set ""h"=a"
set ""i"=b"
set ""j"=c"
set ""k"=d"
set ""l"=e"
set ""m"=f"
set ""n"=g"
set ""o"=h"
set ""p"=i"
set ""q"=j"
set ""r"=k"
set ""s"=l"
set ""t"=m"
set ""u"=n"
set ""v"=o"
set ""w"=p"
set ""x"=q"
set ""y"=r"
set ""z"=s"
set ""~"=!"
set ""^&"=&"
exit /b
Use GnuSed and the "y/abc/tuv/" transliteration command which would replace a with t, b with u and c with v
This syntax works - just extend the character sets:
sed "y/abc/tuv/" "file.txt" >"newfile.txt"

Resources