I am working on a script that edits files and I am building a choice goto menu.
The script itself works fine, it reads from a file name that has ( ) in it. So my files are saved like this (1) filename.txt, (2) filename.txt ....(100) filename.txt
the content of the file has "times": 125489, saved in it, the script removes the 100 from the file name and does this "times": 100,
This is a small part of my content for my txt files it has a 4 indent space per line I believe the format is Json
"aidr": 3.58,
"nlpr": 0.5,
"tafr": 0.5,
"titp": 0.5,
"trld": 0.0,
"tssp": 0.5,
"tssr": 0.5,
"ttup": 0.5,
"ttpp": 0.5,
"times": 125,
"Stamp": 125,
"ppiid": 649,
"otiid": 649,
"apcid": 9,
"orcid": 9,
"jpcns": 0,
"agpns": 0,
"opcns": 0,
"rppns": 0,
I recently found that when I merged all my single scripts together it slows down dramatically. Before the script processed 500 .txt files in 1 minute but now it takes 30 minutes.
My goal is to find a way to bring back the speed of this script.
I heard and read that adding a goto before and after the loop could make the script fast again.
#echo off
:Menu
ECHO ################################################################
echo.
ECHO 1 - Script 1
ECHO 2 - Script 2
ECHO 3 - Script 3
ECHO 4 - Script 4
ECHO 5 - Script 5
ECHO 100 - Script 100
echo.
set pass=
:: the choice command
set /p Mchoice=Make Your Choice:
::goto choices
goto=:%Mchoice%
goto %goto%
:1
#ECHO Off
setlocal ENABLEDELAYEDEXPANSION
set "ToReplace1="times": "
SET "sourcedir=New folder 1"
SET "destdir=New fodler 2"
FOR /f "delims=" %%q IN ('dir /b /a-d "%sourcedir%\(*)*.txt"') DO (
(
FOR /f "tokens=1 delims=()" %%j IN ("%%q") DO (
for /F "tokens=1* delims=:" %%a in ('findstr /N "^" "%sourcedir%\%%q"') do (
set "line=%%b"
if defined line IF "%%b" neq "!line:times=!" CALL :Nums1 %%j
echo(!line!
)
)
)>"%destdir%\%%q"
)
GOTO :Menu
:Nums1
SET "original=%line%"
FOR /L %%s IN (0,1,9) DO set "line=!line:%ToReplace1%%%s=%ToReplace1%!"
IF "%original%" neq "%line%" goto Nums1
set "line=!line:%ToReplace1%=%ToReplace1%%1!"
GOTO :eof
:2
#ECHO Off
setlocal ENABLEDELAYEDEXPANSION
set "ToReplace2="Stamp": "
SET "sourcedir=New folder 1"
SET "destdir=New fodler 2"
FOR /f "delims=" %%q IN ('dir /b /a-d "%sourcedir%\(*)*.txt"') DO (
(
FOR /f "tokens=1 delims=()" %%j IN ("%%q") DO (
for /F "tokens=1* delims=:" %%a in ('findstr /N "^" "%sourcedir%\%%q"') do (
set "line=%%b"
if defined line IF "%%b" neq "!line:Stamp=!" CALL :Nums2 %%j
echo(!line!
)
)
)>"%destdir%\%%q"
)
GOTO :Menu
:Nums2
SET "original=%line%"
FOR /L %%s IN (0,1,9) DO set "line=!line:%ToReplace2%%%s=%ToReplace2%!"
IF "%original%" neq "%line%" goto Nums1
set "line=!line:%ToReplace2%=%ToReplace2%%1!"
GOTO :eof
:15
#ECHO Off
setlocal ENABLEDELAYEDEXPANSION
cd /d "%~dp0"
set "ToReplace1="times": "
set "ToReplace2="Stamp": "
set "ToReplace3="jpcns": "
SET "sourcedir15=New folder 1"
SET "destdir15=New fodler 2"
FOR /f "delims=" %%q IN ('dir /b /s /a-d "%sourcedir15%\(*)*.txt"') DO (
SET "newdest=%%~dpq"
SET "newdest=!newdest:%sourcedir15%=%destdir15%!"
SET "newdest=!newdest:~0,-1!"
MD "!newdest!" 2>nul
(
FOR /f "tokens=1 delims=()" %%j IN ("%%~nxq") DO (
for /F "tokens=1* delims=:" %%a in ('findstr /N "^" "%%q"') do (
set "line=%%b"
if defined line IF "%%b" neq "!line:times=!" CALL :Nums15 %%j
if defined line IF "%%b" neq "!line:Stamp=!" CALL :Nums15 %%j
if defined line IF "%%b" neq "!line:jpcns=!" CALL :Nums15 %%j
echo(!line!
)
)
)>"!newdest!\%%~nxq"
)
GOTO :Menu
:Nums15
SET "original=%line%"
FOR /L %%s IN (0,1,9) DO set "line=!line:%ToReplace1%%%s=%ToReplace1%!"
FOR /L %%s IN (0,1,9) DO set "line=!line:%ToReplace2%%%s=%ToReplace2%!"
FOR /L %%s IN (0,1,9) DO set "line=!line:%ToReplace3%%%s=%ToReplace3%!"
IF "%original%" neq "%line%" goto Nums15
set "line=!line:%ToReplace1%=%ToReplace1%%1!"
set "line=!line:%ToReplace2%=%ToReplace2%%1!"
set "line=!line:%ToReplace3%=%ToReplace3%%1!"
GOTO :eof
I've done a few exercises on this problem, but I've been unable to locate anything that might result in a 30:1 speed difference.
This version
FOR /f "delims=" %%q IN ('dir /b /a-d "%sourcedir%\(*)*.txt"') DO (
(
FOR /f "tokens=1 delims=()" %%j IN ("%%q") DO (
for /F "tokens=1* delims=:" %%b in ('findstr /N "^" "%sourcedir%\%%q"') do (
set "line=%%c"
if defined line (
IF "%%c" equ "!line:times=!" (ECHO %%c) ELSE (
for /F "tokens=1* delims=:" %%v in ("%%c") do ECHO %%v: %%j,
)
) ELSE ECHO(
)
)
)>"%destdir%\%%q"
)
Seemed to be a little faster.
This:
FOR /f "delims=" %%q IN ('dir /b /a-d "%sourcedir%\(*)*.txt"') DO (
(
FOR /f "tokens=1 delims=()" %%j IN ("%%q") DO (
SET "skipover="
for /F "tokens=1* delims=:" %%a in ('findstr /N "^" "%sourcedir%\%%q"') do (
IF DEFINED skipover (ECHO(%%b
) ELSE (
set "line=%%b"
if defined line IF "%%b" neq "!line:times=!" SET "skipover=y"&CALL :Nums1 %%j
echo(!line!
)
)
)
)>"%destdir%\%%q"
)
uses a Boolean variable skipover to bypass some of the processing once the target line has been found and manipulated - but it actually seemed slower.
This
FOR /f "delims=" %%q IN ('dir /b /a-d "%sourcedir%\(*)*.txt"') DO (
(
FOR /f "tokens=1 delims=()" %%j IN ("%%q") DO (
for /F "tokens=1* delims=:" %%b in ('findstr /N "^" "%sourcedir%\%%q"') do (
set "line=%%c"
if defined line (
IF "%%c" equ "!line:times=!" (ECHO %%c) ELSE (
for /F "tokens=1* delims=:" %%v in ("%%c") do ECHO %%v: %%j,
)
) ELSE ECHO(
)
)
)>"%destdir%\%%q"
)
was consistently a little faster than the original - it avoids the subroutine call.
And this:
FOR /f "delims=" %%q IN ('dir /b /a-d "%sourcedir%\(*)*.txt"') DO (
(
FOR /f "tokens=1 delims=()" %%j IN ("%%q") DO (
SET "skipover="
for /F "usebackqdelims=" %%e in ("%sourcedir%\%%q") do (
IF DEFINED skipover (ECHO/%%e
) ELSE (
set "line=%%e"
if defined line (
IF "%%e" equ "!line:times=!" (ECHO %%e
) ELSE (
SET "skipover=Y"
for /F "tokens=1* delims=:" %%v in ("%%e") do ECHO %%v: %%j,
)
) ELSE ECHO/
)
)
)
)>"%destdir%\%%q"
)
was consistently nearly twice as fast, using the skip-if-it's been-changed technique and avoiding findstr. It won't reproduce empty lines, though.
I also found that the position of the target in the source was signiificant. Using a 700-line version of the sample data, placing the target at the end was half-speed of placing it at the start of the file, so I was able to get nearly a 4:1 speed difference between the original and this last technique if the target was placed early in the source data (running 1,000 700-line files).
I presume that sub appeared in the original post by way of editing-out the irrelevant portions of the code, but it seemed to be reversed in sense, the way it was written...
--- based on version 3,
:: remove variables starting #
FOR /F "delims==" %%e In ('set # 2^>Nul') DO SET "%%e="
:: Read controls from file "%1"
FOR /f "usebackqtokens=1*" %%b IN ("%~1") DO (
SET "#%%b=%%c"
FINDSTR /x /i /L /c:":#%%b" <"%~f0" >NUL
IF ERRORLEVEL 1 ECHO LABEL ":#%%b" NOT found&SET "destdir="
)
IF NOT DEFINED destdir ECHO Required LABEL(s) NOT found &GOTO :eof
FOR /f "delims=" %%q IN ('dir /b /a-d "%sourcedir%\(*)*.txt"') DO (
(
rem %%q contains the name of the file to be processed
rem remove variables starting $
FOR /F "delims==" %%e In ('set $ 2^>Nul') DO SET "%%e="
rem extract filenumber if sourcefilename is (number)something
SET "filenumber="
FOR /f "tokens=1 delims=()" %%j IN ("%%q") DO SET "filenumber=%%j"
rem
rem now process the file
for /F "tokens=1* delims=:" %%b in ('findstr /N "^" "%sourcedir%\%%q"') do (
set "line=%%c"
if defined line (
rem if any #name is detected, take action
SET "processline=Y"
FOR /f "tokens=1,2delims=#=" %%u IN ('set #') DO IF DEFINED processline IF "%%c" neq "!line:%%u=!" (
SET "processline="
CALL :#%%u %%v
)
IF DEFINED processline ECHO %%c
) ELSE ECHO/
)
)>"%destdir%\%%q"
)
GOTO :eof
:#times
rem replace times value with filenumber
ECHO "times": %filenumber%,
GOTO :eof
:#titp
rem replace titp value with value read from file (%1)
ECHO "titp": %1,
GOTO :eof
:#tssp
rem put newz value before and zwen value after tssp value
ECHO "newz": whatever,
ECHO %line%
ECHO "zwen": revetahw,
GOTO :eof
:#trld
rem delete all trld values
GOTO :eof
:#tssr
rem replace the third and the fifth tssr value (I have multiples)
rem note that all $ variables are deleted FOR each file
SET /a $#tssr+=1
IF %$#tssr%==3 ECHO "tssr": thirdtime,&GOTO :eof
IF %$#tssr%==5 ECHO "tssr": fifthtime,&GOTO :eof
ECHO %line%
GOTO :eof
Using a control file contents
times #
titp jello
trld #
tssp #
tssr #
So - this is an attempt to obviate the repeated cloning of the file-processing logic.
First, I'm setting all variables that start # to nothing, un-defining them. That way, the remainder of the code knows that any variable starting # has not been inherited from elsewhere.
Next step : read the file to set up
#times=#
#titp=jello
#trld=#
#tssp=#
#tssr=#
The code then examines itself to make sure that subroutines :#times etc all exist and complains if they don't. destdir is simply a convenient non-empty variable used as a flag - we'll abort if the subroutines are missing, so no problem there.
Next - read the filenames. Obviously, the filemask may change depending on the selection made from the menu.
Then, for each file, kill all $ variables for the same reason as # but this time for each file to be processed.
Then set up variables to contain whatever data about the file is appropriate. Could be size, date, whatever - extract-parenethesised-number is shown. No harm in doing such things for all files, even if the data is not used for this particular menu selection.
Then process the file, detecting the keystrings from the # array. Call :#keystring if found, regurgitate line if not.
Each :# routine does what it does. A variety of possibilities is shown. Naturally, any particular routine could be controlled further by testing the selection made.
Setting the value assigned to #? to a value other than # will deliver that value to the :#? subroutine as parameters. Use them as you will - constants, whatever - just interpret the parameters delivered.
Naturally, you could set the # variables manually for particular menu selections instead of reading them from a file.
But - this is drifting way away from the timing problem - just adding more facilities (I'm a chronic implementor of bells and whistles) so I'd suggest to end discussion here.
#echo off
cd /d D:\
setlocal enabledelayedexpansion
set /p "var=v3 "
set "file=Rev.bat"
for /F "tokens=1,* delims==" %%i in ('findstr "%var%" Rev.bat') do (
set "versionVar=%%~i"
set "versionVal=%%~j"
set /a sequence=%%~j+1
)
for /f "tokens=1,*delims=]" %%i in ('type "%file%" ^| find /v /n "" ^& break^>%file%') do (
set "line=%%j"
if "!line!" == "!versionVar!=!versionVal!" set line=!versionVar!=!sequence!
echo(!line!>>!file!
)
I tried this code it doesn't find the string
ok, so if I understand you correctly, this is what you're looking for:
#echo off
cd /d D:\
setlocal enabledelayedexpansion
set "file=rev.bat"
for /F "tokens=1,* delims==" %%i in ('findstr "%~1" rev.bat') do (
set "versionVar=%%~i"
set "versionVal=%%~j"
set /a sequence=%%~j+1
)
for /f "tokens=1,*delims=]" %%i in ('type "%file%" ^| find /v /n "" ^& break^>%file%') do (
set "line=%%j"
if "!line!" == "!versionVar!=!versionVal!" set line=!versionVar!=!sequence!
echo(!line!>>!file!
)
Explanation. We get the file content, using find to assign row id's Then we do search and replace and simply remove the row id's. Then write back everything to the file including the updated version.
note, you need to run the script with a parameter, i.e. script.cmd v3
Edit. to do more than one variable at a time by request, do:
#echo off
cd /d D:\
setlocal enabledelayedexpansion
:Begin
set /p "var=enter variable to replace [.ie v1, v2, v3]: "
set "file=rev.bat"
for /F "tokens=1,* delims==" %%i in ('findstr "%var%" rev.bat') do (
set "versionVar=%%~i"
set "versionVal=%%~j"
set /a sequence=%%~j+1
)
for /f "tokens=1,*delims=]" %%i in ('type "%file%" ^| find /v /n "" ^& break^>%file%') do (
set "line=%%j"
if "!line!" == "!versionVar!=!versionVal!" set line=!versionVar!=!sequence!
echo(!line!>>!file!
)
Hello I was told to ask another question
I would like to see how to add this line to my current script
FOR /f "delims=" %%q IN ('dir /b /s /a-d "%source%\(1)*.txt"') DO (
Or if I can get the help updating "File" and "Filename" to this (1) *.txt this would great as well
#ECHO OFF
SETLOCAL
ECHO STARTING 1
For %%G In ("%~dp0..\New Folder 1") Do Set "source=%%~fG"
For %%G In ("%~dp0..\New Folder 2") Do Set "target=%%~fG"
For %%G In ("%~dp0..\New Folder 3") Do Set "destdir=%%~fG"
set "FILE=(1) Homes in Texas.txt"
set "FILENAME=(1) Homes in Texas.txt"
for /f "tokens=1 delims=[]" %%a in ('find /n "appi"^<"%source%\%file%"') do set /a start=%%a
for /f "tokens=1 delims=[]" %%a in ('find /n "opcn"^<"%source%\%file%"') do set /a end=%%a
(
for /f "tokens=1* delims=[]" %%a in ('find /n /v ""^<"%source%\%file%"') do (
IF %%a geq %start% IF %%a leq %end% ECHO(%%b
)
)>"%target%\(A)_sets.txt"
for /f "tokens=1 delims=[]" %%a in ('find /n "paid"^<"%source%\%file%" ') do set /a start=%%a
for /f "tokens=1 delims=[]" %%a in ('find /n "whbn"^<"%source%\%file%" ') do set /a end=%%a
(
for /f "tokens=1* delims=[]" %%a in ('find /n /v ""^<"%source%\%file%" ') do (
IF %%a geq %start% IF %%a leq %end% ECHO(%%b
)
)>"%target%\(B)_sets.txt"
If Exist "%target%\*.txt" If Exist "%destdir%\" (
Copy /Y /B "%target%\(A)_Sets.txt" + "%target%\(B)_Sets.txt" "%destdir%\(1).txt"
)
ren "%destdir%\(1).txt" "%filename%"
If Exist "%source%\(2) *.txt" (
call "%~dp0(2) Extraction tool.bat"
)
GOTO :EOF
Now I would like to keep this script the speed on my script is very fast it can edit my files at 1 sec per file
I'm OK with using a partial Filename
Because of my setup it makes for no errors, it's super fast speed and all files have these in the filename (?)
With the way I have my setup my workstation, I would have to edit my scripts over and over to match the file name, so I'm trying to use these (1) *.txt, because all my txt file look like this
Sub Houston Folder
(1) Houston.txt
(2) Houston.txt
(3) Houston.txt
Sub Auston Folder
(1) Austin.txt
(2) Austin.txt
Sub Dallas Folder
(1) Dallas.txt
(2) Dallas.txt
(3) Dallas.txt
I have over 5000 files easy
They all have (?) in the file name so looking for (1) *.txt, but don't know if this will be an issue with ren "%destdir%\(1).txt" "%filename%" using (1) *.txt
If there is a way to fix my File and Filename to work on (1) *.txt and to keep the original file name as end result that would be very appreciated
Any Help will be great
Is this correct, when I set this up this way or any other way I get blank files [corrected code below. Stephan]
REM not here... set "FILE=%~1"
set "FILENAME=(1) Homes in Texas.txt"
FOR /f "delims=" %%q IN ('dir /b /s /a-d "%source%\(1)*.txt"') DO call :label "%%q"
goto :eof
:Label
REM here "%~1" gets the value "%%q" from the CALL command, a FQDN (filename including drive and path because of 'dir /s /b')
for /f "tokens=1 delims=[]" %%a in ('find /n "appi"^<"%~1"') do set /a start=%%a
My Setup Folders
Main Folder
|Extraction Batch Folder
|New Folder 1
|all original txt files
|New Folder 2
|all extracted txt files
|New Folder 3
|all renamed and merged files
It's now almost ready We got File fixed with that line
still working on Filename
If Exist "%target%\*.txt" If Exist "%destdir%\" (
Copy /Y /B "%target%\(A)_Sets.txt" + "%target%\(B)_Sets.txt" "%destdir%\(1).txt"
)
ren "%destdir%\(1).txt" "%filename%"
I know that wildcards does work with ren I tested this to confirm *
If Exist "%target%\*.txt" If Exist "%destdir%\" (
Copy /Y /B "%target%\(A)_Sets.txt" + "%target%\(B)_Sets.txt" "%destdir%\(1).txt"
)
ren "%destdir%\(1).txt" "(*)A.txt"
and in %destdir% it rename to (1)A.txt so the wild card sees the (1)
how can I set this up to take the matching (1) on the filename located in the source folder and use that to rename the (1).txt found in `%destdir% folder
So if I run findstr and it doesn't find any matching strings it leaves this weird symbol in the file instead:
And it does that at the end of almost all of my files as well. Is there a way to get rid of that or stop it from happening? Later I have it check if the file is empty or not to set a true/false and that symbol is screwing with those results. I have alot of checks in the same program running one after the other, is there something I need to do between them that will stop it?
As an example, this code doesn't do that:
ECHO Scanning files for Risks
(
FOR /F "delims=" %%a in ('findstr /I /L "android:allowBackup android:backupagent" AndroidManifest.xml') DO (
SET "line=%%a"
SET "line=!line:*android:allowBackup=!"
SET "line=!line:*android:backupagent=!"
FOR /F "delims=<" %%b in (!line!) DO ECHO %%b
)) > ScanResults.txt
But this one does:
ECHO Scanning files for Risks
(
FOR /F "tokens=1*delims=:" %%a in ('findstr /I /S "web" *.smali') DO (
SET "line=%%b"
SET "line=!line:*web=!"
FOR /F "delims=<>" %%b in ("!line!") DO ECHO %%a:%%b
)) > ScanResults.txt
UPDATE: Even with the two things added it still puts the weird symbol into the text file instead of having it empty
ECHO Scanning files for Risks
(
FOR /F "tokens=1*delims=:" %%a in ('findstr /I /S "web" *.smali 2^>NUL') DO (
SET "line=%%b"
SET "line=!line:*web=!"
FOR /F "delims=^<^>" %%b in ("!line!") DO ECHO %%a:%%b
)) > ScanResults.txt
UPDATE: To further clarify I'm searching a variety of files as previously stated, the most common being JSON and smali files in order to double check my own work. But really it searches through everything, the code is just a series of searches like the code above with just *.smali changed to *.xml or *.json or whatever is needed. So the section of code that is producing the weird symbol in its search looks like this:
ECHO off
SETLOCAL enabledelayedexpansion
(
FOR /F "delims=" %%a in ('findstr /I /S "web" AndroidManifest.xml') DO (
SET "line=%%a"
SET "line=!line:*web=!"
FOR /F "delims=<>" %%b in ("!line!") DO ECHO %%b
)) > ScanResults1.txt
REM scans all JSON files
(
FOR /F "tokens=1*delims=:" %%a in ('findstr /I /S "web" *.json') DO (
SET "line=%%b"
SET "line=!line:*web=!"
FOR /F "delims=<>" %%b in ("!line!") DO ECHO %%a:%%b
)) > ScanResults2.txt
REM scans all html files
(
FOR /F "tokens=1*delims=:" %%a in ('findstr /I /S "web" *.html') DO (
SET "line=%%b"
SET "line=!line:*webv=!"
FOR /F "delims=<>" %%b in ("!line!") DO ECHO %%a:%%b
)) > ScanResults3.txt
REM scans all xml files
(
FOR /F "tokens=1*delims=:" %%a in ('findstr /I /S "web" *.xml') DO (
SET "line=%%b"
SET "line=!line:*web=!"
FOR /F "delims=<>" %%b in ("!line!") DO ECHO %%a:%%b
)) > ScanResults4.txt
REM scans all smali files
(
FOR /F "tokens=1*delims=:" %%a in ('findstr /I /S "web" *.smali') DO (
SET "line=%%b"
SET "line=!line:*web=!"
FOR /F "delims=<>" %%b in ("!line!") DO ECHO %%a:%%b
)) > ScanResults5.txt
COPY ScanResults1.txt + ScanResults2.txt + ScanResults3.txt + ScanResults4.txt + ScanResults5.txt ScanResultsA.txt
DEL ScanResults1.txt
DEL ScanResults2.txt
DEL ScanResults3.txt
DEL ScanResults4.txt
DEL ScanResults5.txt
:eof
The output file looks like:
That's the weird symbol I keep getting when it doesn't find anything. It won't keep it if its copied and pasted over so I had to do a picture.
If there are no finds, output should be empty and nothing passed to the for (code block)
except an error message from findstr itself not redirected to nul.
So append 2^>NUL to the findstr
FOR /F "tokens=1*delims=:" %%a in ('findstr /I /S "web" *.smali 2^>NUL') DO (
I have a program to ping computers, check there registry, and tell me the results.
I am now trying to script it so that I don't have to know the ip address just the host name of the computer.
I found a script to give me the ip off of a hostname
for /f "tokens=1,2 delims=[]" %%a in ('ping -4 %%a ^| find "Pinging"') do set ip=%%c >nul
I have tried to simply insert this into a biger loop that uses a file to give it the host names.
for /f %%A in (%1) do (
for /f "tokens=1,2 delims=[]" %%a in ('ping -4 %%a ^| find "Pinging"') do (
set host=%%a
set ip=%%c
echo "."
echo %ip% %host%
pause
) >>%2
)
I have also tried it like this,
for /f %%a in (%1) do (
set /p hostname=%%a
for /f "tokens=1,2 delims=[]" %%b in ('ping -4 %%a ^| find "Pinging"') do set ip=%%c >nul
echo %ipaddress% %hostname%
)
Please any help on this would be greatly appreciated.
Thank you.
AFTER MUTCH HEAD BANGING
#echo off
SETLOCAL EnableDelayedExpansion
for /f %%A in (%1) do (
for /f "tokens=1,2 delims=[]" %%a in ('ping /4 /n 1 %%A ^| findstr "Pinging"') do echo "%%A %%b"
)