Computing.Net > Forums > Programming > xp batch script

Computing.Net: Over 1,000,000 posts about all things technology related! Over 90% answered within 24 hours! Click here to sign up now, it's free!

xp batch script

Reply to Message Icon

Original Message
Name: edman747
Date: January 21, 2007 at 18:00:02 Pacific
Subject: xp batch script
OS: xp home/pro
CPU/Ram: 2.8ghz/1gb
Model/Manufacturer: hp
Comment:

new to batch scripting. would it be possible to have a script that can read a list of file names from a directory and determine if there is a series ie. file1.txt file2.txt then append a line to a configuration file that points to the next file name in the series?
like file1.cfg would have the following line added:
nextmap file2
---
loosely this will type a list of file names.
for %%x in (*.bsp) do echo %%x

--- strip file extensions
--- look at %current and %next file name
--- is it a series
--- echo nextmap %next >> %current + .cfg

any help will be appreciated, tia


background and purpose:
Half-Life mod Sven Co-op
recent updates to the steam(content distribution system) have uncovered a changelevel bug in the Sven Co-op mod.

this bug prevents the server from automaticaly changing to the next map, when a trigger_changelevel is encountered.
a workaround is to include a nextmap statement in each maps config file.

a script would help to do this for hundreds of maps on hundreds of computers most running xp or xp pro.

single or non series maps can be skipped.
like auspices.bsp

a series would have the cfg files updated.
for example, the map series.
toonrun1.bsp
toonrun2.bsp
toonrun3.bsp

toonrun1.cfg add nextmap toonrun2
toonrun2.cfg add nextmap toonrun3
toonrun3.cfg no change

hostage.bsp
hostage2a.bsp
hostage2b.bsp

afrikakorps1.bsp
afrikakorps2.bsp
afrikakorps3.bsp

this will not fix the half-life single player maps. since the correct sequence cannot be determined by the map name.
c1a0c.bsp no change
c1a0d.bsp no change
c1a4j.bsp no change
c1a0c runs after c1a0d in the sequence.

It's OK, I've already done them.


Report Offensive Message For Removal


Response Number 1
Name: edman747
Date: January 22, 2007 at 14:20:55 Pacific
Reply: (edit)

here is what I've got.
@echo off
setlocal enabledelayedexpansion
if exist filenames.txt del filenames.txt
for %%x in (*.bsp) do echo %%x >>filenames.txt
for /f "tokens=* delims=" %%a in (filenames.txt) do (
set txtline=%%a
set txtline=!txtline:.bsp=!
echo !txtline!>>tmp.txt)
del filenames.txt & ren tmp.txt filenames.txt
endlocal

reads file names from a directory into text file. strips off the file name extension.
I don't know how to compare the file names or
do sub string manipulation.



Report Offensive Follow Up For Removal

Response Number 2
Name: edman747
Date: January 23, 2007 at 20:29:48 Pacific
Reply: (edit)

this batch script will quickly generate mapnames.txt

@echo off
if exist mapnames.txt del mapnames.txt
@FOR /f "delims=" %%? IN ('DIR/b *.bsp') DO @ECHO/%%~n? >>filenames.txt

here I attempt to describe the problem differently.
map names are sequential. typically map1 map2 map3, sometimes map map2a map2b map3
made up of a mapname and an extension or modifier as the number and everything following it.
ie. map2a is mapname = map plus a modifier = 2a
mapnames.txt is sorted directory listing of map names with the .bsp extension stripped.

read a line from mapnames.txt
mapname = line
process mapname one character at a time
if a number is found save the number and everything after it.
modifier = "whatever"
no number found
modifier = ""
mapname = line - modifier

read the nextline from mapnames.txt
mapname2 = line
process mapname2 one character at a time
if a number is found save the number and everything after it.
modifier2 = "whatever"
no number found
modifier2 = ""
mapname2 = line - modifier2

if mapname is like mapname2
append one line of text to the file: mapname + modifier + .cfg
the line would be: nextmap mapname + modifier2

read the nextline from mapnames.txt
mapname3 = line
process mapname3 one character at a time
if a number is found save the number and everything after it.
modifier3 = "whatever"
no number found
modifier3 = ""
mapname3 = line - modifier3

if mapname is like mapname3
append one line of text to the file: mapname + modifier2 + .cfg
the line would be: nextmap mapname + modifier3

keep doing this until mapname is not like mapname?n


Report Offensive Follow Up For Removal

Response Number 3
Name: edman747
Date: January 24, 2007 at 20:44:26 Pacific
Reply: (edit)

here is what I've got so far. a little broken when it comes to the odd case hostage hostage2a hostage2b. and for opening the correct file to append a line.
any help?

Option Explicit
Dim objFSO
Dim ofolder
Dim objStream

Dim intCounter
Dim arrTestNames ()
Dim dicBaseNames
Dim strBase
Dim strName
Dim strNumber
Dim nUBound
Dim arrTemp
Dim strOutput

Set objFSO = CreateObject("Scripting.FileSystemObject")

'create the output file
Set objStream = objFSO.createtextfile("search.log", True)
CheckFolder (objFSO.getfolder(".")), objStream
ReDim Preserve arrTestNames (intCounter)
FillArray(objFSO.getfolder(".")), objStream, arrTestNames

'Start by making a dictionary of all the base names. The value will be an array of the numerals
Set dicBaseNames = CreateObject("Scripting.Dictionary")
For Each strName In arrTestNames
strBase = GetBaseName(strName)
strNumber = GetSequenceNumber(strName)
If dicBaseNames.Exists(strBase) Then
nUBound = UBound(dicBaseNames(strBase)) + 1
arrTemp = dicBaseNames(strBase)
ReDim Preserve arrTemp(nUBound)
arrTemp(nUBound) = strNumber
dicBaseNames(strBase) = arrTemp
Else
dicBaseNames.Add strBase, Array(strNumber)
End If
Next

'now step through the dictionary using basenames.
StepThruDic(objFSO.getfolder(".")), objStream

MsgBox "File Search Completed." + vbCr + "Please check search.log for details."

Function GetSequenceNumber(strName)
Dim oRE
Dim colMatches
Dim oMatch

Set oRE = New Regexp
oRE.Pattern = "\D*(\d*)(\D*)"
oRE.IgnoreCase = True
Set colMatches = oRE.Execute(strName)
For Each oMatch In colMatches
GetSequenceNumber = oMatch.Submatches(0)
Exit Function
Next
GetSequenceNumber = ""
End Function

Function GetBaseName(strName)
Dim oRE
Dim colMatches
Dim oMatch

Set oRE = New Regexp
oRE.Pattern = "(\D*)\d*(\D*)"
oRE.IgnoreCase = True
Set colMatches = oRE.Execute(strName)
For Each oMatch In colMatches
GetBaseName = oMatch.SubMatches(0)
Exit Function
Next
GetBaseName = "ERROR"
End Function

Sub CheckFolder(objCurrentFolder, objLogFile)

Dim strTemp
Dim strSearch
Dim strOutput
Dim objNewFolder
Dim objFile
Dim objStream
dim a

strSearch = ".bsp"

For Each objFile In objCurrentFolder.Files
strTemp = Right(objFile.Name, 4)
If UCase(strTemp) = UCase(strSearch) Then
'Got one
'a=Split(CStr(objFile.Name),".")
intCounter = intCounter + 1
'strOutput = CStr(intCounter) & " " & a(0)
'objLogFile.writeline strOutput
End If
Next

End Sub

Sub FillArray(objCurrentFolder, objLogFile, arrTestNames)

Dim strTemp
Dim strSearch
Dim strOutput
Dim objNewFolder
Dim objFile
Dim objStream
dim a
dim intIndex

strSearch = ".bsp"

intIndex = 0
For Each objFile In objCurrentFolder.Files
strTemp = Right(objFile.Name, 4)
If UCase(strTemp) = UCase(strSearch) Then
'Got one
a=Split(CStr(objFile.Name),".")
'populate database
arrTestNames (intIndex) = a(0)
'strOutput = arrTestNames (intIndex)
'objLogFile.writeline strOutput
intIndex = intIndex + 1
End If
Next

End Sub

Sub StepThruDic(objCurrentFolder, objLogFile)

Dim strTemp
Dim strSearch
Dim strOutput
Dim objNewFolder
Dim objFile
Dim objStream
dim a
dim intIndex
dim strName2
dim strBase2
dim strNumber2
dim strName3
dim strBase3
dim strNumber3
dim i

For i = 0 to intCounter - 1
strName = arrTestNames(i)
strBase = GetBaseName(strName)
strNumber = GetSequenceNumber(strName)
If strNumber = "" Then
strName2 = arrTestNames(i + 1)
strBase2 = GetBaseName(strName2)
If StrComp(strBase2, strBase) = 0 Then
strNumber2 = GetSequenceNumber(strName2)
strOutput = "nextmap" & " " & strbase2 & strnumber2 & " " & strname & ".cfg"
objLogFile.writeline strOutput
End If
If strNumber2 = "1" Then
strName3 = arrTestNames(i + 2)
strBase3 = GetBaseName(strName3)
If StrComp(strBase3, strBase) = 0 Then
strNumber3 = GetSequenceNumber(strName3)
strOutput = "nextmap" & " " & strbase3 & strnumber3 & " " & strname2 & ".cfg"
objLogFile.writeline strOutput
End If
End If
End If

If strNumber = "1" Then
strName2 = arrTestNames(i + 1)
strBase2 = GetBaseName(strName2)
If StrComp(strBase2, strBase) = 0 Then
strNumber2 = GetSequenceNumber(strName2)
strOutput = "nextmap" & " " & strbase2 & strnumber2 & " " & strname & ".cfg"
objLogFile.writeline strOutput
End If
If strNumber2 = "2" Then
strName3 = arrTestNames(i + 2)
strBase3 = GetBaseName(strName3)
If StrComp(strBase3, strBase) = 0 Then
strNumber3 = GetSequenceNumber(strName3)
strOutput = "nextmap" & " " & strbase3 & strnumber3 & " " & strname2 & ".cfg"
objLogFile.writeline strOutput
End If
End If
End If
Next

End Sub


Report Offensive Follow Up For Removal

Response Number 4
Name: edman747
Date: February 8, 2007 at 10:09:32 Pacific
Reply: (edit)

hello, thanks for your help. here is the near final vbscript. it still has a little trouble with some filename series projectg, projectg1 ... project8 does not get the nonnumber one first.

tweaked the regex to better split the filenames into character / number parts. found and online regex tester that helped.

it is updated to sort the dictionary by the key. and when an item is a number it sorts the rest of the items as numbers.

had to include special case stuf to handle names starting with numbers and names that are one number.
if anyone is real smart with vbscript. have a look. if not maybe something here will help you. thanks.
[code][codebox]Option Explicit
Dim objFSO
Dim ofolder
Dim objStream
Dim objStream2
Dim intCounter
Dim arrTestNames ()
Dim dicBaseNames
Dim strBase
Dim strName
Dim strNumber
Dim nUBound
Dim arrTemp
Dim strOutput, a
Const dictKey = 1
Const dictItem = 2

Set objFSO = CreateObject("Scripting.FileSystemObject")
'create the output file
Set objStream = objFSO.CreateTextFile("search3.log", True)
CheckFolder (objFSO.GetFolder(".")), objStream
ReDim Preserve arrTestNames (intCounter)
FillArray(objFSO.GetFolder(".")), objStream, arrTestNames

Const TextCompare = 1
'Start by making a dictionary of all the base names. The value will be an array of the numerals
Set dicBaseNames = CreateObject("Scripting.Dictionary")
dicBaseNames.CompareMode = TextCompare
For Each strName In arrTestNames
strBase = GetBaseName(strName)
strNumber = GetSequenceNumber(strName)
'workaround for single number names.
If strbase = "1" Then
strbase = "jam"
strNumber = "1"
End If
If strbase = "2" Then
strbase = "jam"
strNumber = "2"
End If
If strbase = "3" Then
strbase = "jam"
strNumber = "3"
End If
If strbase = "4" Then
strbase = "jam"
strNumber = "4"
End If
If strbase = "5" Then
strbase = "jam"
strNumber = "5"
End If
If strbase = "6" Then
strbase = "jam"
strNumber = "6"
End If
If dicBaseNames.Exists(strBase) Then
nUBound = UBound(dicBaseNames(strBase)) + 1
arrTemp = dicBaseNames(strBase)
ReDim Preserve arrTemp(nUBound)
arrTemp(nUBound) = strNumber
dicBaseNames(strBase) = arrTemp
Else
dicBaseNames.Add strBase, Array(strNumber)
End If
Next

set dicbasenames = SortDictionary(dicBaseNames, dictKey)
'set dicbasenames = sortdict(dicbasenames,objFSO.getfolder("."), objStream)
'step through the dictionary using basenames and numbers to update config files.
StepThruDic(objFSO.GetFolder(".")), objStream

MsgBox "Series Map Search Completed." + vbCr + "Please check updated map.cfg's." + vbCr + "See search.log for details " + CStr(Date)

Function SortDictionary(ByVal objDict, intSort)
' declare our variables
Dim strDict()
Dim arrTmp()
Dim objKey
Dim strKey, strItem
Dim X, Y, Z, i, j, temp

' get the dictionary count
Z = objDict.Count

' we need more than one item to warrant sorting
If Z > 1 Then
' create an array to store dictionary information
ReDim strDict(Z, 2)
X = 0
' populate the string array
For Each objKey In objDict
ReDim arrTmp(UBound(objdict(objkey)))
For i = 0 To UBound(objdict(objkey)) '- 1
arrTmp(i) = objDict.Item(objKey)(i)
Next
For i = UBound(objdict(objkey)) - 1 To 0 step -1
For j = 0 To i
If objKey <> "c" Then
If Len(arrTmp(j)) <> 0 And Len(arrTmp(j + 1)) <> 0 Then
If IsNumeric(arrTmp(j)) And IsNumeric(arrTmp(j + 1)) Then
If CInt(arrTmp(j)) > CInt(arrTmp(j + 1)) Then
Wscript.Echo CStr(Join(arrTmp))
temp = arrTmp(j + 1)
arrTmp(j + 1) = arrTmp(j)
arrTmp(j) = temp
End If
End If
End If
End If
Next
Next
strDict(X, dictKey) = CStr(objKey)
strDict(X, dictItem) = CStr(Join(arrTmp))
X = X + 1
Next

' perform a a shell sort of the string array
For X = 0 To (Z - 2)
For Y = X To (Z - 1)
If StrComp(strDict(X, intSort), strDict(Y, intSort), vbTextCompare) > 0 Then
strKey = strDict(X, dictKey)
strItem = strDict(X, dictItem)
strDict(X, dictKey) = strDict(Y, dictKey)
strDict(X, dictItem) = strDict(Y, dictItem)
strDict(Y, dictKey) = strKey
strDict(Y, dictItem) = strItem
End If
Next
Next

' erase the contents of the dictionary object
objDict.RemoveAll

' repopulate the dictionary with the sorted information
For X = 0 To (Z - 1)
objDict.Add strDict(X, dictKey), Split(strDict(X, dictItem))
Next

End If

Set SortDictionary = objDict

End Function

Function GetSequenceNumber(strName)
Dim oRE
Dim colMatches
Dim oMatch, I

Set oRE = New Regexp
'oRE.Pattern = "\D*(\d*)(.*$)"
oRE.Pattern = "[^\D]*\D*(\d*.*$)"
oRE.IgnoreCase = True
Set colMatches = oRE.Execute(strName)
If colMatches.Count > 0 Then
Set omatch = colMatches(0)
If oMatch.SubMatches.Count > 0 Then
For I = 0 To oMatch.SubMatches.Count -1
GetSequenceNumber = GetSequenceNumber & oMatch.SubMatches(I)
Next
End If
Else
GetSequenceNumber = ""
End If
'For Each oMatch In colMatches
' GetSequenceNumber = oMatch.SubMatches(0) & oMatch.SubMatches(1)
' Exit Function
'Next
'GetSequenceNumber = ""
End Function

Function GetBaseName(strName)
Dim oRE
Dim colMatches
Dim oMatch, I

Set oRE = New Regexp
'oRE.Pattern = "(\D*)\d*"
oRE.Pattern = "^(\d*\D*)\d*"
oRE.IgnoreCase = True
Set colMatches = oRE.Execute(strName)
If colMatches.Count > 0 Then
Set oMatch = colMatches(0)
If oMatch.Submatches.Count > 0 Then
For I = 0 To oMatch.SubMatches.Count -1
GetBaseName = GetBaseName & oMatch.SubMatches(I)
Next
End If
End If
'For Each oMatch In colMatches
' GetBaseName = oMatch.SubMatches(0)
' Exit Function
'Next
'GetBaseName = "ERROR"
End Function

Sub CheckFolder(objCurrentFolder, objLogFile)

Dim strTemp
Dim strSearch
Dim strOutput
Dim objNewFolder
Dim objFile
Dim objStream
Dim a

strSearch = ".bsp"

For Each objFile In objCurrentFolder.Files
strTemp = Right(objFile.Name, 4)
If UCase(strTemp) = UCase(strSearch) Then
intCounter = intCounter + 1
End If
Next

End Sub

Sub FillArray(objCurrentFolder, objLogFile, arrTestNames)

Dim strTemp
Dim strSearch
Dim strOutput
Dim objNewFolder
Dim objFile
Dim objStream
Dim a
Dim intIndex

strSearch = ".bsp"

intIndex = 0
For Each objFile In objCurrentFolder.Files
strTemp = Right(objFile.Name, 4)
If UCase(strTemp) = UCase(strSearch) Then
arrTestNames (intIndex) = Split(objFile.Name, ".")(0)
intIndex = intIndex + 1
End If
Next

End Sub

Sub StepThruDic(objCurrentFolder, objLogFile)

Dim strTemp
Dim strSearch
Dim strOutput
Dim objNewFolder
Dim objFile
Dim objStream
Dim i, j, temp, num1, num2
Dim strNextmap

strOutput = "changelevel bug squished. Summary of changes:"
objLogFile.WriteLine strOutput
For Each strBase in dicBaseNames.Keys
For i = 0 To UBound(dicBaseNames(strBase)) - 1
If strbase = "jam" Then
strOutput = dicBaseNames(strBase)(i) & ".cfg"
objLogFile.WriteLine strOutput
strOutput = " nextmap " & dicBaseNames(strBase)(i + 1)
objLogFile.WriteLine strOutput
'update the config file.
If objFSO.FileExists(dicBaseNames(strBase)(i) & ".cfg") Then
objFSO.OpenTextFile(dicBaseNames(strBase)(i) & ".cfg", 8).WriteLine _
vbCrLf & "nextmap " & dicBaseNames(strBase)(i + 1)
Else
'create the config file.
strTemp = dicBaseNames(strBase)(i) & ".cfg"
Set objStream = objFSO.CreateTextFile(strTemp, True)
objStream.WriteLine _
"nextmap " & dicBaseNames(strBase)(i + 1)
End If

Else
'skip c1,c2,c3 series, blank records, special case
If strBase <> "c" _
And "nextmap " & strbase & dicBaseNames(strBase)(i) <> "nextmap " Then
strNextmap = strbase & dicBaseNames(strBase)(i + 1)
If strBase & dicBaseNames(strBase)(i) = "assaultmesa2-2" Then
strOutput = strBase & dicBaseNames(strBase)(i + 1) & ".cfg"
objLogFile.WriteLine strOutput
strOutput = " nextmap " & strBase & dicBaseNames(strBase)(i)
objLogFile.WriteLine strOutput
If objFSO.FileExists(strBase & dicBaseNames(strBase)(i + 1) & ".cfg") Then
objFSO.OpenTextFile(strBase & dicBaseNames(strBase)(i + 1) & ".cfg", 8).WriteLine _
vbCrLf & "nextmap " & strbase & dicBaseNames(strBase)(i)
End If
Else
' write to the search log.
strOutput = strBase & dicBaseNames(strBase)(i) & ".cfg"
objLogFile.WriteLine strOutput
strOutput = " nextmap " & strNextmap
objLogFile.WriteLine strOutput

'update the config file.
If objFSO.FileExists(strBase & dicBaseNames(strBase)(i) & ".cfg") Then
objFSO.OpenTextFile(strBase & dicBaseNames(strBase)(i) & ".cfg", 8).WriteLine _
vbCrLf & "nextmap " & strbase & dicBaseNames(strBase)(i + 1)
Else
'create the config file.
strTemp = strBase & dicBaseNames(strBase)(i) & ".cfg"
Set objStream = objFSO.CreateTextFile(strTemp, True)
objStream.WriteLine _
"nextmap" & " " & strbase & dicBaseNames(strBase)(i + 1)
End If
End If
End If
End If
Next
Next
End Sub[/code][/codebox]


Report Offensive Follow Up For Removal







Post Locked

This post is quite old and has been locked from receiving new replies. Please create a new posting instead.


Go to Programming Forum Home








Do you have your own blog?

Yes
No
I did before
I will soon


View Results

Poll Finishes In 4 Days.
Discuss in The Lounge
Poll History




Data Recovery Software