parse the source safe history output and run the diff command - batch-file

I am fairly new to writing batch scripts. I am trying to write a script file to achieve the following task.
I have a source safe command below to get the list of files changed between two dates
ss.exe history $/myproject -Vd04/01/2012~01/01/2012 -R
The output of the above command is as follows
Building list for $/myproject.......................................................
....................................................................................
...................................
***** AllPages.master *****
Version 67
User: user1 Date: 1/12/12 Time: 1:08p
Checked in $/myproject/websites/website1
Comment:
***** AdminTSSetup.aspx.vb *****
Version 10
User: user2 Date: 1/12/12 Time: 1:09 p
Checked in $/myproject/websites/website1
Comment:
With the output above, I want to read the file name (allpages.master, AdminTsSetup.aspx.vb) and version of each file from the output and run the following command
SS diff -DS <filename from output> -V<version from output - 1>~<version from output>
Basically, I was trying to compare the previous version with the current version for each file in the output.
Can some one please help?

This should give you what you asked for. But it seems like the diff command you specified is missing a reference to the project.
This solution should work even if the file name contains spaces, !, ;, or any special characters like & or ^.
#echo off
setlocal disableDelayedExpansion
for /f "delims=*" %%A in ('ss.exe history $/myproject -Vd04/01/2012~01/01/2012 -R ^| findstr /b "***** Version"') do (
set "ln=%%A"
setlocal enableDelayedExpansion
if "!ln:~0,1!"==" " (
for /f "eol=: delims=" %%F in ("!ln:~1!") do (
endlocal
set "file=%%~nxF"
)
) else (
for /f "tokens=2 delims= " %%V in ("!ln!") do (
set /a "version1=%%V, version0=version1-1"
ss.exe dif -DS "!file!" -V!version0!~!version1!
endlocal
)
)
)
Here is a version that adds the project information from the "Checked in" line
#echo off
setlocal disableDelayedExpansion
for /f "delims=*" %%A in ('ss.exe history $/myproject -Vd04/01/2012~01/01/2012 -R ^| findstr /b "***** Version Checked"') do (
set "ln=%%A"
setlocal enableDelayedExpansion
if "!ln:~0,1!"==" " (
for /f "eol=: delims=" %%F in ("!ln:~1!") do (
endlocal
set "file=%%~nxF"
)
) else if "!ln:~0,1!"=="V" (
for /f "tokens=2 delims= " %%V in ("!ln!") do (
endlocal
set /a "version1=%%V, version0=version1-1"
)
) else (
for /f "tokens=2* delims= " %%B in ("!ln!") do (
endlocal
set "proj=%%C"
setlocal enableDelayedExpansion
ss.exe dif -DS "!proj!/!file!" -V!version0!~!version1!
endlocal
)
)
)

Basically you need a for loop and a little state:
#echo off
setlocal enabledelayedexpansion
for /f "tokens=1,2 delims= " %%i in ('ss.exe history $/myproject -Vd04/01/2012~01/01/2012 -R') do (
if "%%i"=="*****" (
rem a file name
set "FileName=%%j"
) else (
if "%%i"=="Version" (
set Version=%%j
set /a LastVersion=Version - 1
ss diff -DS "!FileName!" -V!LastVersion!~!Version!
set FileName=&set Version=&setLastVersion=
)
)
)
Should kinda work, I guess.

Related

Calling a function for every attribute I want to read from multiple .txt files and write to .csv file

I tried to call a function for every attribute (column) that I want to read from 4 .txt files and then write into a .csv file. One column has flawed output and the code should have a few logic flaws as I haven't learned batch cleanly from scratch. Do you know a fix?
Link to previous solved question: Read information from multiple .txt files and sort it into .csv file
#Magoo
echo Name;Prename;Sign;Roomnumber;Phonenumber > sorted.csv
for /f "tokens=1,2 delims= " %%a in (TestEmployees.txt) do (
call :findSign %%a %%b
)
:findSign
set prename=%1
set name=%2
for /f "tokens=1,2 delims= " %%a in (TestSign.txt) do (
if "%name%"=="%%a" (
call :findRoomNumber
)
)
:End
:findRoomNumber
set sign=%1
for /f "tokens=1,2 delims=|" %%q in (TestRoomNumber.txt) do (
if "%sign%"=="%%q" (
call :findPhoneNumber
)
)
:End
:findPhoneNumber
for /f "tokens=1,2 delims=;" %%u in (TestPhoneNumber.txt) do (
if "%%b"=="%%u" (
echo %name%;%prename%;%%b;%%r;%%v >> sorted.csv
)
)
:End
This is the way I would do it:
#echo off
setlocal EnableDelayedExpansion
rem Load PhoneNumber array
for /F "tokens=1,2 delims=;" %%a in (PhoneNumber.txt) do set "phone[%%a]=%%b"
rem Load RoomNumber array
for /F "tokens=1,2 delims=|" %%a in (RoomNumber.txt) do set "room[%%a]=%%b"
rem Load Sign array
for /F "tokens=1,2" %%a in (Sign.txt) do set "sign[%%a]=%%b"
rem Process Employees file and generate output
> sorted.csv (
echo Name;Prename;Sign;RoomNumber;PhoneNumber
for /F "tokens=1,2" %%a in (Employees.txt) do for %%s in (!sign[%%b]!) do (
echo %%b;%%a;%%s;!room[%%s]!;!phone[%%s]!
)
)
#ECHO OFF
SETLOCAL
rem The following settings for the directories and filenames are names
rem that I use for testing and deliberately includes spaces to make sure
rem that the process works using such names. These will need to be changed to suit your situation.
SET "sourcedir=u:\your files"
SET "destdir=u:\your results"
SET "filename1=%sourcedir%\q74258020_TestEmployees.txt"
SET "filename2=%sourcedir%\q74258020_TestSign.txt"
SET "filename3=%sourcedir%\q74258020_TestRoomNumber.txt"
SET "filename4=%sourcedir%\q74258020_TestPhoneNumber.txt"
SET "outfile=%destdir%\outfile.txt"
>"%outfile%" (
echo Surname;Name;Sign;Roomnumber;Phonenumber
for /f "usebackqtokens=1,2 delims= " %%g in ("%filename1%") do (
call :findSign %%g %%h
)
)
GOTO :eof
:findSign
for /f "usebackqtokens=1,2 delims= " %%b in ("%filename2%") do (
if "%2"=="%%b" (
for /f "usebackqtokens=1,2 delims=|" %%q in ("%filename3%") do (
if "%%c"=="%%q" (
for /f "usebackqtokens=1,2 delims=;" %%u in ("%filename4%") do (
if "%%c"=="%%u" (
echo %2;%1;%%c;%%r;%%v
)
)
)
)
)
)
GOTO :EOF
Always verify against a test directory before applying to real data.
Note that if the filename does not contain separators like spaces, then both usebackq and the quotes around %filename1% can be omitted.
Why should I not upload images of code/data/errors? Copy and paste the code as text
For similar reasons, please post all relevant data into a question to obviate every potential respondent having to switch back and forth to the data to which you have linked.

find and replace a string in xml using batch

Sample input:
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_WINDOWS;_DEBUG;NEWCODE;% (PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
Intended output:
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_LARGE_;WIN32;_WINDOWS;_DEBUG;NEWCODE;% (PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
Current output when running batch multiple times:
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_LARGE;_LARGE_;WIN32;_WINDOWS;_DEBUG;NEWCODE;% (PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
Batch file:
#echo off
setlocal enableextensions enabledelayedexpansion
set "textFile="C:\"
set "file2=%textFile%\sample.vcxproj"
set list=%file2%
set "WIN32=^<PreprocessorDefinitions^>"
set "LARGE_=_LARGE_;"
set "replace=%WIN32%_LARGE_;"
set "cmd=%1"
set "append=enable"
set "remove=disable"
set "empty="
echo %replace% !WIN32!
(for %%a in (%list%) do (
IF "%cmd%"=="%remove%" (
echo removed
for /f "delims=" %%i in ('type %%a ^& break ^> %%a ') do (
set "line=%%i"
setlocal enabledelayedexpansion
>>"%%a" echo(!line:%LARGE_DICOM%=%empty%!
endlocal
)
)
IF "%cmd%"=="%append%" (
echo append
echo %%a
for /f "delims=" %%i in ('type %%a ^& break ^> %%a ') do (
set "line=%%i"
Echo "%%i" |findstr /R "%replace%" 1>nul
if %errorlevel%==0 (
echo eexist
)
setlocal enabledelayedexpansion
>>"%%a" echo(!line:%WIN32%=%replace%!
endlocal
)
)
echo %%a
))
I am trying to find LARGE in preprocessor, if not exist add it, but it is adding multiple times
Find and, search is not working. I need to append only if it not exist.
Append to file if particular sting not found, string should append once, even if we run batch multiple times.

Batch file: count duplicate ids and write them in column of csv

I am currently trying to automate the preprocessing process on a csv file via a batch file. I have the following table:
id;street;name;nrOfIds
4014001;T1;example1;0
4014002;B2;example2;0
4014003;B3;example3;0
4014004;L1;example4;0
4015001;M3;example5;0
4015002;B9;example6;0
4016001;T4;example7;0
4016002;L2;example8;0
4016003;L1;example9;0
The first row "id" holds the id of the entry which is made unique by the last 3 digts (for example 001, 002, 003, ...). The digits before the last three digits are not unique. As you can see in the result table, I want to count how often the first part of the ID (so the part before the last three digits) exists in the table and I want to write the sum into the third column named "nrOfIds". The result table then should look like this:
id;street;name;nrOfIds
4014001;T1;example1;4
4014002;B2;example2;4
4014003;B3;example3;4
4014004;L1;example4;4
4015001;M3;example5;2
4015002;B9;example6;2
4016001;T4;example7;3
4016002;L2;example8;3
4016003;L1;example9;3
For example, the part before the last three digits of the first line (4014) exists exactly 4 times in the whole table, so I write 4 in the "nrOfIds" column and so on.
The code used for this looks like this:
#echo off
setlocal enabledelayedexpansion
for /F "tokens=1-3* delims=;" %%a in (%PREPROCESSING_INPUT_PATH%%INPUT_FILENAME%) do (
(echo %%a;%%b;%%c)> "%PREPROCESSING_INPUT_PATH%%OUTPUT_FILENAME%" & goto :file
)
:file
(for /F "skip=1 tokens=1-3* delims=;" %%a in (%PREPROCESSING_INPUT_PATH%%INPUT_FILENAME%) do (
REM count ids (like 4014, 4015, ... and write sum into "nrOfIds" column
)
) >> %PREPROCESSING_OUTPUT_PATH%%OUTPUT_FILENAME%
pause
Any suggestions on how to do this? Thank you very much in advance! Your help is greatly appreciated.
Pretty similar to the previous answer I posted, here we just use find /C to identify the number of occurrences of the last 3 digits of the ID:
#echo off
setlocal enabledelayedexpansion
set "infile=z:\folder31\testcsv.csv"
set "outfile=%PREPROCESSING_OUTPUT_PATH%testOutput.csv"
for /f "usebackq delims=" %%a in ("%infile%") do (
(echo %%a)>"%outfile%" & goto :file
)
:file
(for /f "skip=1 usebackq tokens=1-4*delims=;" %%a in ("%infile%") do (
set "match=%%a"
for /f %%i in ('findstr /B "!match:~0,-3!" "%infile%" ^| find /C "!match:~0,-3!"') do (
set /a _cnt=%%i
echo %%a;%%b;%%c;!_cnt!
)
)
)>>"%outfile%"
Debug version:
#echo off
setlocal enabledelayedexpansion
set "infile=%PREPROCESSING_INPUT_PATH%%INPUT_FILENAME%"
set "outfile=%PREPROCESSING_OUTPUT_PATH%%OUTPUT_FILENAME%"
for /f "usebackq delims=" %%a in ("%infile%") do (
(echo %%a) & goto :file
)
:file
(for /f "skip=1 usebackq tokens=1-4*delims=;" %%a in ("%infile%") do (
set "match=%%a"
for /f %%i in ('findstr /B "!match:~0,-3!" "%infile%" ^|find /C "!match:~0,-3!"') do (
set /a _cnt=%%i
echo %%a;%%b;%%c;!_cnt!
)
)
)
pause
This method is simple and run fast:
#echo off
setlocal enabledelayedexpansion
rem Count ids
for /F "skip=1 delims=;" %%a in (input.txt) do (
set "id=%%a"
set /A "count[!id:~0,-3!]+=1"
)
rem Update the file
set "header="
(for /F "tokens=1-4 delims=;" %%a in (input.txt) do (
if not defined header (
echo %%a;%%b;%%c;%%d
set "header=1"
) else (
set "id=%%a"
for /F %%i in ("!id:~0,-3!") do echo %%a;%%b;%%c;!count[%%~i]!
)
)) > output.txt
A method based on external commands, like findstr or find, is slower...

"The system cannot find file" error in batch script

I'm trying to set the contents of a file to my variable 'reportPath'. The variable 'latestReport' holds the path to the file. When I run this command
for /F %%z in (%latestReport%) do set "reportPath=%%z"
I get the error mentioned in the title of this question ("The system cannot find file"). However, if I replace %latestReport% with the path to the file, the code executes perfectly.
How do I get the code to read my %latestReport% variable as a filename?
Here is the whole script:
#echo off
setLocal Enabledelayedexpansion
set "subject="
set "reportPath="
if "%1"=="" (
for /F "delims== tokens=2" %%a in ('findstr /B test_report_directory my_file_here.properties') do set testReportDir=%%a
set "subject=RentalMan Test Execution Results"
goto :runemaildriver
)
set testReportDir=%~f1
if not exist %testReportDir% (
:: finds string test_report_directory in config file
for /F "delims== tokens=2" %%a in ('findstr /B test_report_directory my_file_here.properties') do set "testReportDir=%%a"
) else (
shift
)
if "%1"=="" (
set "subject=RentalMan Test Execution Results"
) else (
for %%a in (%*) do (
if not exist %%a (
set "subject=!subject!%%a "
)
)
set "subject=!subject:~0,-1!"
)
:runemaildriver
echo testReportDir: %testReportDir%
set latestReport=%testReportDir%\currrentReportPath.txt
echo latestReport: %latestReport%
for /F %%z in (%latestReport%) do set "reportPath=%%z"
echo reportPath: %reportPath%
for /F "delims=: tokens=2" %%d in ('findstr \B Environment %reportPath%') do set "env=%%d"
echo env: %env%
echo Emailing latest TestReport in %testReportDir% with subject line "%subject%"...

How to get a Substring from list of file names

I want to develop the following logic
Read all files in a directory
Extract the first part of the filename – this will be the partner name
Extract anything after the first underscore- this will be filename
Eg: ZZTEST_123_abc_doc.txt  ZZTEST is partner. 123_abc_doc.txt is the filename.
Below is the code I developed
#echo off
setlocal ENABLEDELAYEDEXPANSION
Set Test_Dir=C:\Axway\projects\Cardinal\dosscript\test
cd %Test_Dir%
for /r %%a in (*.*) do (
Set "fname1=%%~nxa"
echo Filename is :!fname1!
for /f "tokens=1 delims=_" %%i in ("!fname1!") do (
Set "partner=%%i"
echo Partner is :!partner!
Set "str_tmp=!partner!_"
echo !str_tmp!
call :strlength length !str_tmp!
echo !length!
set fname=!fname1:~%length%!
echo !fname1:~%length%!
)
)
goto :eof
:strlength
setlocal enableextensions
set "#=%~2"
set length=0
:stringLengthLoop
if defined # (set "#=%#:~1%"&set /A length+=1&goto stringLengthLoop)
endlocal && set "%~1=%length%"
GOTO :EOF
But the result is
ID_ZZRoutingID_filename.txt
Filename is :ZZRoutingID_ZZRoutingID_filename1.txt
Partner is :ZZRoutingID
12
Result: ID_ZZRoutingID_filename1.txt
The result should be ZZRoutingID_filename1.txt but i am getting
ID_ZZRoutingID_filename1.txt.
Please help
The purpose of the length calculation is not clear to me, but I would suggest adding an asterisk following the 1 in your for /f "tokens=1 delims=_". You would then get the "filename" you were looking for through %%j.
I tested it like this:
#echo off
setlocal EnableDelayedExpansion
set source=D:\Program Files\Somewhere
cd %source%
for /r %%i in (*.*) do (
for /f "tokens=1* delims=_" %%j in ( "%%~nxi" ) do (
echo partner: %%j
echo name: %%k
)
)
endlocal
If you do not need to recurse through sub-directories:
#echo off
set source=D:\Program Files\Somewhere
for /f "tokens=1* delims=_" %%i in ( 'dir "%source%" /b /a-d' ) do (
echo partner: %%i
echo filename: %%j
)
dir /b /a-d retrieves the list of a directory's content except its sub-directories:
D:\Program Files\Somewhere>dir /b /a-d
ZZTEST_123_456.txt
ABCDEF_890_FFF.doc
FOOBAR_567_###.zzz

Resources