Batch check and replace string then wait for a process - windows

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.

Related

add a "pre_value" to set /p userinp=

I have following code, asking for user to fill in filename:
echo Type in your filename (path + filename):
set userinp=
set /p userinp= ^>
What I would like:
already 'prefill' fullpath+filename, which the user can then edit.
In most cases, this would be: %cd%+filename (most common file selected)
Type in your filename (path + filename):
> D:\Download\MyFile.txt
(the string 'D:\Download\MyFile.txt' should be editable)
NB: must be achieved strictly with Windows batch commands; no use of the other languages and/or programs.
This method is simple and have the advantage that you may use the standard command-line navigation keys, that is, besides the edition you may enter the first letters of a folder/file and browse through the existent folders/files with TAB key. You may even put "{TAB}" in the prefill value to automatically prefill with the first file in current directory, or "Dat{TAB}" for the first file that start with "Dat", etc.
#if (#CodeSection == #Batch) #then
#echo off
echo Type in your filename (path + filename):
cscript //nologo //E:JScript "%~F0" "%cd%\commonFile.ext"
set "userinp="
set /P "userinp=>"
echo Value read: "%userinp%"
goto :EOF
#end
WScript.CreateObject("WScript.Shell").SendKeys(WScript.Arguments(0));
Note that the cscript command, used here to execute a line of JScript code, is a standard "DOS" command provided with all Windows versions since XP on.
EDIT: Include the path of first file
You may put "%cd%\{TAB}" in the prefill value in order to get the first file in current folder including the path; however, this method fail if the path contain any space. The new code below fix this point, although it still may fail if at any point in the path exist two folders with same name until the first space and the wanted folder is not the first one.
#if (#CodeSection == #Batch) #then
#echo off
setlocal EnableDelayedExpansion
set "curdir="
for %%a in ("%cd:\=" "%") do (
for /F "tokens=1*" %%b in (%%a) do (
set "curdir=!curdir!\%%b"
if "%%c" neq "" set "curdir=!curdir!{TAB}"
)
)
echo Type in your filename (path + filename):
cscript //nologo //E:JScript "%~F0" "%curdir:~1%\{TAB}"
set "userinp="
set /P "userinp=>"
echo Value read: "%userinp%"
goto :EOF
#end
WScript.CreateObject("WScript.Shell").SendKeys(WScript.Arguments(0));
Code taken from aGerman on Dostips.com
#echo off &setlocal
call :PredefInput "Type in your filename (path + filename):>" "D:\Download\MyFile.txt" filename
echo Your filename is %filename%
pause
goto :eof
:::::::::: END ::::::::::
:PredefInput ByVal_Message ByVal_Predefined ByRef_VarName
if "%__PRIN__%" neq "__PRIN__" (
setlocal DisableDelayedExpansion
if "%~3"=="" endlocal &exit /b 0
set "M=%~1" &set "S=%~2" &set "N=0" &set "__PRIN__=__PRIN__"
for /f %%i in ('"prompt;$h&for %%i in (1) do rem"') do set "BS=%%i"
setlocal EnableDelayedExpansion
<nul set /p "=.!BS! !BS!!M!!S!"
set "S=A!S!"
for /l %%i in (12,-1,0) do (
set /a "N|=1<<%%i"
for %%j in (!N!) do if "!S:~%%j,1!"=="" set /a "N&=~1<<%%i"
)
for %%i in (!N!) do endlocal &set "N=%%i"
)
set "C="
for /f "delims=" %%i in ('2^>nul xcopy /lw "%~f0" "%~f0"') do if not defined C set "C=%%i"
set "C=%C:~-1%"
setlocal EnableDelayedExpansion
if not defined C (
echo(
if defined S (
for /f delims^=^ eol^= %%i in ("!S!") do endlocal &endlocal &set "%~3=%%i" &exit /b %N%
) else endlocal &endlocal &set "%~3=" &exit /b 0
)
if "!BS!"=="!C!" (
set "C="
if defined S set /a "N -= 1" &set "S=!S:~,-1!" &<nul set /p "=%BS% %BS%"
) else set /a "N += 1" &<nul set /p "=.%BS%!C!"
if not defined S (
endlocal &set "N=%N%" &set "S=%C%"
) else for /f delims^=^ eol^= %%i in ("!S!") do endlocal &set "N=%N%" &set "S=%%i%C%"
goto PredefInput

How to assign call argument to var and echo it in Windows batch script

I want to do this:
set kommune
FOR /F "tokens=* delims=" %%x in (DBLib.txt) DO (
CALL :decryptLine "%%x"
)
GOTO:eof
:decryptLine
for /f "tokens=1,* delims==" %%a in ("%~1") do set argument=%%a & set value=%%b
set "argument=%argument:~0,-2%"
set "value=%value:~1%"
call:updateVar "%argument%" "%value%"
GOTO:EOF
:updateVar
IF "%~1" == "KommuneNavn" (
ECHO "%~2"
ECHO "KommuneNavn"
set kommune=%~2
ECHO kommune = "%kommune%" testhest
)
What it outputs:
"ABC Test Kommune"
"KommuneNavn"
"kommune = "" testhest"
How do i copy the value of the secont argument to the Variable "kommune"? And Echo it?
Edit 1: updated to exact code. "inside IF"
#ECHO OFF
SETLOCAL
set kommune
FOR /F "tokens=* delims=" %%x in (q27922463.txt) DO (
CALL :decryptLine "%%x"
)
GOTO:eof
:decryptLine
for /f "tokens=1,* delims==" %%a in ("%~1") do set "argument=%%a" & set "value=%%b"
set "argument=%argument:~0,-2%"
set "value=%value:~1%"
call:updateVar "%argument%" "%value%"
GOTO:EOF
:updateVar
IF "%~1" == "KommuneNavn" (
ECHO "%~2"
ECHO "KommuneNavn"
set kommune=%~2
CALL ECHO kommune = "%%kommune%%" testhest
)
GOTO :eof
Critical point: You haven't shown us the content of your file, so we have to construct it: and I've changed the filename to suit my system (q27922463.txt)
contents of q27922463.txt
KommuneNavnxy=yourvalue
output generated:
"ourvalue"
"KommuneNavn"
kommune = "ourvalue" testhest
Note the positioning of the quotes in the set assignments. Batch is sensitive to spaces in a SET statement. SET FLAG = N sets a variable named "FLAGSpace" to a value of "SpaceN"
So, %%a becomes KommuneNavnxy, is assigned to argument, and the last 2 characters are removed, making KommuneNavn
Similarly, %%b gets yourvalue, you remove the first and make ourvalue
Since the string kommune is set within the code block of the if statement, you need to use call echo %%var%% to display it (one of several ways).

Windows batch file to find duplicates in a tree

I need a batch file ( Windows CMD is the interpreter, a .bat ) to do this type of task:
1) Search through a folder and its subfolders
2) Find files with the same filename and extension ( aka duplicates )
3) Check if they have the same size
4) If same name + same size, echo all the files except the first one ( practically I need to delete all except one copy )
Thanks for any type of help
This is only an initial script, just for check the files, in a folder and its subfolders, and their size:
#Echo off
Setlocal EnableDelayedExpansion
Set Dir=C:\NewFolder
For /r "%Dir%" %%i in (*) do (
Set FileName=%%~nxi
Set FullPath=%%i
Set Size=%%~zi
Echo "!FullPath!" - SIZE: !Size!
)
Echo.
Pause
This script does what you ask. Just set the ROOT variable at the top to point to the root of your tree.
#echo off
setlocal disableDelayedExpansion
set root="c:\test"
set "prevTest=none"
set "prevFile=none"
for /f "tokens=1-3 delims=:" %%A in (
'"(for /r "%root%" %%F in (*) do #echo %%~znxF:%%~fF:)|sort"'
) do (
set "currTest=%%A"
set "currFile=%%B:%%C"
setlocal enableDelayedExpansion
if !currTest! equ !prevTest! echo "!currFile!"
endlocal
set "prevTest=%%A"
)
But you can make the test more precise by using FC to compare the contents of the files. Also, you can incorporate the DEL command directly in the script. The script below prints out the commands that would delete the duplicate files. Remove the ECHO before the DEL command when you are ready to actually delete the files.
#echo off
setlocal disableDelayedExpansion
set root="c:\test"
set "prevTest=none"
set "prevFile=none"
for /f "tokens=1-3 delims=:" %%A in (
'"(for /r "%root%" %%F in (*) do #echo %%~znxF:%%~fF:)|sort"'
) do (
set "currTest=%%A"
set "currFile=%%B:%%C"
setlocal enableDelayedExpansion
set "match="
if !currTest! equ !prevTest! fc /b "!prevFile!" "!currFile!" >nul && set match=1
if defined match (
echo del "!currFile!"
endlocal
) else (
endlocal
set "prevTest=%%A"
set "prevFile=%%B:%%C"
)
)
Both sets of code may seem overly complicated, but it is only because I have structured the code to be robust and avoid problems that can plague simple solutions. For example, ! in file names can cause problems with FOR variables if delayed expansion is enabled, and = in file name causes a problem with npocmoka's solution.
#echo off
setlocal
for /f "tokens=1 delims==" %%# in ('set _') do (
set "%%#="
)
for /r %%a in (*.*) do (
if not defined _%%~nxa%%~za (
set "_%%~nxa%%~za=%%~fa"
) else (
echo %%~fa
)
)
endlocal

How to create a unique output filename for Windows Script?

I am trying to create a windows script that should generate this kind of filename everytime I run it: filename1, filename2, filename3 and so on. Here is what I have so far:
(
#echo off
wmic logicaldisk get size,freespace,caption
) > disk.txt
I hope you can help me. Thanks!!
:: make a tempfile
:maketemp
SET "tempfile=%temp%\%random%"
IF EXIST "%tempfile%*" (GOTO maketemp) ELSE (ECHO.>"%tempfile%a")
You now have any number of filenames available.
%tempfile%a exists and is empty, but %tempfile%anythingelse should be available for use.
#ECHO OFF
SETLOCAL
SET "basename=filename"
SET /a outname=0
:genloop
SET /a outname+=1
IF EXIST "%basename% %outname%.txt" GOTO genloop
SET "outname=%basename% %outname%.txt"
ECHO %outname%
GOTO :EOF
Ah - increment the destination filename on each run. This should do that. It's not actually creating a file - you'd need to create the file %outname% each time to have it increment...
(the space between %basename% and %outname% is optional, of course - omit it if desired.)
edited to include .txt
This will give you up to 1000 filenames but you can go higher, up to 2 Billion, but the higher you go the longer the delay will be before it picks a filename.
#echo off
for /L %%a in (1,1,1000) do if not defined filename if not exist "filename%%a.txt" set "filename=filename%%a.txt"
(
wmic logicaldisk get size,freespace,caption
) > "%filename%"
#echo off
setlocal enableextensions
call :getNextFilename "filename*.txt" nextFilename
echo %nextFilename%
echo test > "%nextFilename%"
call :getNextFilename "%cd%\filename*.txt" nextFilename
echo %nextFilename%
echo test > "%nextFilename%"
endlocal
exit /b
:getNextFilename whatToSearch returnVariable
setlocal enableextensions enabledelayedexpansion
for /f %%a in ("$\%~1"
) do for /f "tokens=1,* delims=*" %%b in ("%%~nxa"
) do ( set "left=%%b" & set "right=%%c" )
set "max=0"
for %%a in ("%~1"
) do for /f "tokens=1 delims=%left%%right% " %%b in ("%%~nxa"
) do for /f "tokens=* delims=0 " %%c in ("0%%~b"
) do if %%~c geq !max! set /a "max=%%c+1"
endlocal & set "%~2=%~dp1%left%%max%%right%" & exit /b
This should find the next file in sequence independently of the existence of holes in the numeration of the files. A path can be included or omitted. The * will be used as the placeholder for the numeration. BUT this will not work if files or included paths have "problematic" characters.
If the date/time of creation of the file can be considered, then this version can be optimized as
:getNextFilename whatToSearch returnVariable
setlocal enableextensions disabledelayedexpansion
for /f %%a in ("$\%~1"
) do for /f "tokens=1,* delims=*?" %%b in ("%%~nxa"
) do ( set "left=%%b" & set "right=%%c" )
set "max=0"
for /f "delims=" %%a in ('dir /tc /o-d /b "%~1" 2^>nul'
) do for /f "tokens=1 delims=%left%%right% " %%b in ("%%~nxa"
) do for /f "tokens=* delims=0 " %%c in ("0%%~b"
) do set /a "max=%%c+1" & goto done
:done
endlocal & set "%~2=%~dp1%left%%max%%right%" & exit /b
that will take the latest created instance of the file set.
I finally figured out where to put the .txt extension. This is from #Magoo's answer but I wanted the file to be a text file so I placed the .txt twice in order for it to work properly.
#ECHO OFF
SETLOCAL
SET "basename=DISK-OUT"
SET /a outname=0
:genloop
SET /a outname+=1
IF EXIST "%basename% %outname%.txt" GOTO genloop
SET "outname=%basename% %outname%.txt"
(
wmic logicaldisk get size,freespace,caption
) > "%outname%"
GOTO :EOF

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