I am searching for a VBScript that does a search and replace in files (e.g. 1.txt 2.xml).
I have file "1.txt" that inside there is the word "temporary" and I want to change it to "permanent".
Because I get this file a lot I need a script for it.
Every time that I try to write a script that contains open a txt file and the command replace, it doesn't.
I found a script that change this file with another file and does the change inside, but this is not what I am looking for.
Try this
If WScript.Arguments.Count <> 3 then
WScript.Echo "usage: Find_And_replace.vbs filename word_to_find replace_with "
WScript.Quit
end If
FindAndReplace WScript.Arguments.Item(0), WScript.Arguments.Item(1), WScript.Arguments.Item(2)
WScript.Echo "Operation Complete"
function FindAndReplace(strFilename, strFind, strReplace)
Set inputFile = CreateObject("Scripting.FileSystemObject").OpenTextFile(strFilename, 1)
strInputFile = inputFile.ReadAll
inputFile.Close
Set inputFile = Nothing
Set outputFile = CreateObject("Scripting.FileSystemObject").OpenTextFile(strFilename,2,true)
outputFile.Write Replace(strInputFile, strFind, strReplace)
outputFile.Close
Set outputFile = Nothing
end function
Save this in a file called Find_And_Replace.vbs, it can then be used at the command line like this.
[C:\]> Find_And_Replace.vbs "C:\1.txt" "temporary" "permanent"
*This method is case sensitive "This" != "this"
If you don't want to read the entire file into memory, you could use a temp file like this.
If WScript.Arguments.Count <> 3 then
WScript.Echo "usage: Find_And_replace.vbs filename word_to_find replace_with "
WScript.Quit
end If
FindAndReplace WScript.Arguments.Item(0), WScript.Arguments.Item(1), WScript.Arguments.Item(2)
WScript.Echo "Operation Complete"
function FindAndReplace(strFile, strFind, strReplace)
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objInputFile = objFSO.OpenTextFile(strFile,1)
strTempDir = objFSO.GetSpecialFolder(2)
Set objTempFile = objFSO.OpenTextFile(strTempDir & "\temp.txt",2,true)
do until objInputFile.AtEndOfStream
objTempFile.WriteLine(Replace(objInputFile.ReadLine, strFind, strReplace))
loop
objInputFile.Close
Set objInputFile = Nothing
objTempFile.Close
Set objTempFile = Nothing
objFSO.DeleteFile strFile, true
objFSO.MoveFile strTempDir & "\temp.txt", strFile
Set objFSO = Nothing
end function
You can try this version which doesn't slurp the whole file into memory:
Set objFS = CreateObject("Scripting.FileSystemObject")
strFile=WScript.Arguments.Item(0)
strOld=WScript.Arguments.Item(1)
strNew=WScript.Arguments.Item(2)
Set objFile = objFS.OpenTextFile(strFile)
Do Until objFile.AtEndOfStream
strLine = objFile.ReadLine
if Instr(strLine,strOld)> 0 Then
strLine=Replace(strLine,strOld,strNew)
End If
WScript.Echo strLine
Loop
Usage:
c:\test> cscript //nologo find_replace.vbs file oldtext newtext
Related
I need to insert the contents of a text file into another existing text file after the line with a specific word in it.
Here is my code.
'//OPEN FILE and READ
Set objFileToRead = fso.OpenTextFile(ActiveDocument.Path & "\file.txt", 1)
strFileText = objFileToRead.ReadAll()
objFileToRead.Close
objStartFolder = ActiveDocument.Path
Set objFolder = fso.GetFolder(objStartFolder)
Set colFiles = objFolder.files
For Each objFile In colFiles
If fso.GetExtensionName(objFile.Name) = "opf" Then
filename = objFile.Name
End If
Next
MsgBox filename
'///PASTE
If fso.FileExists(ActiveDocument.Path & "\" & filename) Then
MsgBox filename
Set objFile = fso.OpenTextFile(ActiveDocument.Path & "\" & filename)
Do Until objFile.AtEndOfStream
strLine = objFile.ReadLine
If InStr(strLine, "<manifest>") = 1 Then
MsgBox filename
objFile.WriteLine vbCrLf & strFileText
objFile.Close
End If
Loop
End If
I get a bad file error in the following line
objFile.WriteLine vbCrLf & strFileText
Can anyone please tell me what is wrong and what I have to do?
You can't write to a file that was opened for reading.
Either write the modified content to a temporary file and replace the original file with it afterwards:
p = fso.BuildPathActiveDocument.Path, filename)
Set f1 = fso.OpenTextFile(p)
Set f2 = fso.OpenTextFile(p & ".tmp", 2, True)
Do Until f1.AtEndOfStream
line = f1.ReadLine
f2.WriteLine line
If InStr(line, "<manifest>") = 1 Then f2.WriteLine strFileText
Loop
f1.Close
f2.Close
fso.DeleteFile p, True
fso.GetFile(p & ".tmp").Name = filename
or read the entire content into memory before writing the modified content back to the original file:
p = fso.BuildPathActiveDocument.Path, filename)
txt = Split(fso.OpenTextFile(p).ReadAll, vbNewLine)
Set f = fso.OpenTextFile(p, 2)
For Each line In original
f.WriteLine line
If InStr(line, "<manifest>") = 1 Then f.WriteLine strFileText
Next
f.Close
Note that the latter shouldn't be used for large files, lest your computer come grinding to a halt due to memory exhaustion.
How to replace a specific string with the filename? Example: I have several files with different names (like: Test.asp, Constant.asp, Letter.asp, etc.) within a subfolder that contain the text "ABC123". I would like to replace the "ABC123" in each file with the filename.
Below is the code I have that finds string and replaces it with a specific string but it doesn't do the job that I listed above.
Option Explicit
Dim objFilesystem, objFolder, objFiles, objFile, tFile, objShell, objLogFile,objFSO, objStartFolder, colFiles
Dim SubFolder, FileText, bolWriteLog, strLogName, strLogPath, strCount, strCount2, strOldText, strNewText, strEXT
bolWriteLog = True
Const ForReading = 1
Const ForWriting = 2
Const TriStateUseDefault = -2
Set objFilesystem = WScript.CreateObject("Scripting.FileSystemObject")
Set objShell = CreateObject("WScript.Shell")
strLogName = "log.txt"
strLogPath = "C:\" & strLogName
strCount = 0
strCount2 = 0
strOldText = "ABC123"
strNewText = ""
strEXT = "asp"
'Initialize log file
If bolWriteLog Then
On Error Resume Next
Set objLogFile = objFileSystem.OpenTextFile(strLogPath, 2, True)
WriteLog "############### Start Log ##################"
If Not Err.Number = 0 Then
MsgBox "There was a problem opening the log file for writing." & Chr(10) & _
"Please check whether """ & strLogPath & """ is a valid file and can be openend for writing." & _
Chr(10) & Chr(10) & "If you're not sure what to do, please contact your support person.", vbCritical, "Script Error"
WScript.Quit
End If
On Error Goto 0
End If
Set objFSO = CreateObject("Scripting.FileSystemObject")
objStartFolder = "D:\MyFolder"
Set objFolder = objFSO.GetFolder(objStartFolder)
WScript.Echo objFolder.Path
Set colFiles = objFolder.Files
For Each objFile In colFiles
'WScript.Echo objFile.Name
' Now we have an exception for all files that can not be opened in text modus: all extensions such as "exe" should be listed upfront.
ReplaceText(objFile)
Next
ShowSubfolders objFSO.GetFolder(objStartFolder)
Sub ReplaceText(objFile)
If InStr(1, strEXT, Right(LCase(objFile.Name), 3)) = 0 Or objFile.Size = 0 Then
Else
strCount = strCount + 1
WriteLog("Opening " & objFile.Name)
Set tFile = objFile.OpenAsTextStream(ForReading, TriStateUseDefault)
FileText = tFile.ReadAll
tFile.Close
If InStr(FileText, strOldText) Then
WriteLog("Replacing " & strOldText & " with " & strNewText & ".")
FileText = Replace(FileText, strOldText, strNewText)
WriteLog("Text replaced")
Else
WriteLog(strOldText & " was not found in the file.")
strCount2 = strCount2 + 1
End If
Set tFile = objFile.OpenAsTextStream(ForWriting, TriStateUseDefault)
tFile.Write FileText
tFile.Close
FileText = ""
strCount = 0
strCount2 = 0
End If
End Sub
Sub ShowSubFolders(Folder)
For Each Subfolder in Folder.SubFolders
'WScript.Echo Subfolder.Path
Set objFolder = objFSO.GetFolder(Subfolder.Path)
Set colFiles = objFolder.Files
For Each objFile in colFiles
'WScript.Echo objFile.Name
ReplaceText(objFile)
Next
ShowSubFolders Subfolder
Next
End Sub
WriteLog "############### EndLog ##################"
WScript.Echo "Script Complete"
objShell.Run "C:\" & strLogName
'Clear environment and exit
On Error Resume Next
Set tFile = Nothing
Set objFile = Nothing
Set objFiles = Nothing
Set objFolder = Nothing
Set objLogFile = Nothing
Set objFilesystem = Nothing
Set objShell = Nothing
WScript.Quit
'Subs and functions ********** DO NOT EDIT ***************
Sub WriteLog(sEntry)
If bolWriteLog Then objLogFile.WriteLine(Now() & ": Log: " & sEntry)
End Sub
I can give you a one line Ruby solution, should be not too difficult to translate that in Python but somewhat more extensive in VbScript I am afraid. First a generic search and replace version.
ARGV[0..-3].each{|f| File.write(f, File.read(f).gsub(ARGV[-2],ARGV[-1]))}
Save it in a script, eg replace.rb
You start in on the command line (here cmd.exe) with
replace.rb *.txt <string_to_replace> <replacement>
broken down so that I can explain what's happening but still executable
# ARGV is an array of the arguments passed to the script.
ARGV[0..-3].each do |f| # enumerate the arguments of this script from the first to the last (-1) minus 2
File.write(f, # open the argument (= filename) for writing
File.read(f) # open the argument (= filename) for reading
.gsub(ARGV[-2],ARGV[-1])) # and replace all occurances of the beforelast with the last argument (string)
end
And finally your request to replace ABC123 with the filename.
Of course tested and working
ARGV[0..-1].each{|f| File.write(f, File.read(f).gsub('ABC123', f))}
Contents of one of my testfiles (1.txt) after executing
test phrase
1.txt
EDIT
I see you want subfolder recursion on a fixed folder, no problem
Dir['**/*'].each{|f| File.write(f, File.read(f).gsub('ABC123', f)) unless File.directory?(f) }
I have a directory of files that I want to Loop through and use part of their filename to replace text in a template doc.
For example one filename may be 'NV_AD32_city.dxf'. All files in the directory follow the same filename pattern of XX_XXXX_string.dxf, using two underscores.
I need to capture the string to the right of the first "_" and to the left of the "."so for this example that would be 'AD32_city'
How do I script to use capture that text of the active file to replace text in the template? I guess I need to create an object? But what is the object to use for the current file from a directory?
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Thx for the replies, guys. After several days of trying your code I am just not "getting it". I understand it is set up to take the part of the filename's string that I want but how do I tell the script to use the current file I am looping through? Here is my script so far. I have your code on line 20 under the Sub 'GetNewInputs'
Set fso = CreateObject("Scripting.FileSystemObject")
Option Explicit
Dim WritePath : WritePath = "S:\TempFolder\"
Dim OutFile : OutFile = "VEG_DXF-2-SHP_script-"
Dim WorkingFile : WorkingFile = GetFileContent(SelectFile())
Dim NewState, NewSection, NewArea
Dim OldState, OldSection, OldArea
Call GetNewInputs()
Call GetOldInputs()
Sub GetNewInputs()
NewState = UCase(InputBox("INPUT STATE:", _
"INPUT STATE", "SOCAL"))
NewSection = ("Section_" & InputBox("INPUT SECTION NUMBER:", _
"INPUT SECTION", "14"))
NewArea = "^[^_]+_(.*)\.dxf$"
End Sub
Private Sub GetOldInputs()
OldState = "XX"
OldSection = "_X"
OldArea = "ZZZZ"
End Sub
Function SelectFile()
SelectFile = vbNullString
Dim objShell : Set objShell = WScript.CreateObject("WScript.Shell")
Dim strMSHTA : strMSHTA = "mshta.exe ""about:" & "<" & "input type=file id=FILE>" _
&"<" & "script>FILE.click();new ActiveXObject('Scripting.FileSystemObject')" _
&".GetStandardStream(1).WriteLine(FILE.value);close();resizeTo(0,0);" & "<" & "/script>"""
SelectFile = objShell.Exec(strMSHTA).StdOut.ReadLine()
If SelectFile = vbNullString Then
WScript.Echo "No file selected or not a text file."
WScript.Quit
End If
End Function
Private Function GetFileContent(filePath)
Dim objFS, objFile, objTS
Set objFS = CreateObject("Scripting.FileSystemObject")
Set objFile = objFS.GetFile(filePath)
Set objTS = objFile.OpenAsTextStream(1, 0)
GetFileContent = objTS.Read(objFile.Size)
Set objTS = Nothing
End Function
For Each FileRefIn fso.GetFolder("S:\SOCAL\Section_14\Veg DXFs\").Files
NewFile = WorkingFile
NewFile = Replace(NewFile, OldState, NewState)
NewFile = Replace(NewFile, OldSection, NewSection)
NewFile = Replace(NewFile, OldArea, NewArea)
WriteFile NewFile, WritePath & OutFile & ".gms"
WScript.Echo NewArea
Next
Private Sub WriteFile(strLine,fileName)
On Error Resume Next
Dim objFSO, objFile
Set objFSO = CreateObject("Scripting.FileSystemObject")
Do Until IsObject(objFile)
Set objFile = objFSO.OpenTextFile(fileName, 8, True)
Loop
objFile.WriteLine strLine
objFile.Close
End Sub
Well, that’s actually two questions.
To enumerate files in a directory, you can use FileSystemObject, like this (untested)
const strFolderPath = "C:\Temp\Whatever"
set objFSO = CreateObject( "Scripting.FileSystemObject" )
set objFolder = objFSO.GetFolder( strFolderPath )
set colFiles = objFolder.Files
for each objFile in colFiles
' Do whatever you want with objFile
next
Here's the reference of those objects properties/methods.
And to extract portion of file names, you could use a regular expression.
Here’s some guide how to use'em in VBScript.
The following expression should work for you, it will capture the portion of that file names you asked for:
"^[^_]+_(.*)\.dxf$"
If you need to edit the content of the .dxf files, you will need to work within the AutoCAD VBA (Visual Basic for Applications) environment.
If that is the case, you will need to start with something like below:
GetObject("AutoCAD.Application.20")
CreateObject("AutoCAD.Application.20")
https://knowledge.autodesk.com/search-result/caas/CloudHelp/cloudhelp/2015/ENU/AutoCAD-ActiveX/files/GUID-0225808C-8C91-407B-990C-15AB966FFFA8-htm.html
** Please take note that "VBA is no longer distributed with the AutoCAD installation; it must be downloaded and installed separately. The VBA Enabler for Autodesk AutoCAD can be downloaded here."
I have made the script FindAndReplace.vbs which simply watches a folder and finds any desired string in the filenames and replaces that string with a desired string.
Now, What I´m trying to create is a VBScript (ConfigureFindAndReplace.vbs) that will easily configure the following 3 things in the FindAndReplace.vbs code:
Browse and select which folder to watch (targetPath)
Which text string to search for in the filenames of the files inside this folder (strFind)
Which string to replace with (strReplace)
I want the script to be user friendly for users with no programming skills.
And I want the main executable script FindAndReplace.vbs to automatically be updated EVERY time the ConfigureFindAndReplace.vbs is run.
To better help you understand here is th
e link to a .zip file containing both of the above mentioned files. This is as far as I can get and I´ve been stuck for 2 days now:
https://www.dropbox.com/s/to3r3epf4ffyedb/StackOverFlow.zip?dl=0
Hope I explained it properly. If not, let me know whatever you need to know.
Thanks in advance:)
And here are the codes from the files:
ConfigureFindAndReplace.vbs:
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objShell = CreateObject ("Shell.Application")
Set objTFolder = objShell.BrowseForFolder (0, "Select Target Folder", (0))
targetPath = objTFolder.Items.Item.Path
Dim oFSO
Set oFSO = CreateObject("Scripting.FileSystemObject")
sScriptDir = oFSO.GetParentFolderName(WScript.ScriptFullName) & "/"
strFind = InputBox("Add string to find.","String to Find", "")
If strFind = "" Then
Wscript.Quit
End If
strReplace = InputBox("Add string to replace with.","Replace with", "")
Dim VarFind
Dim VarReplace
Dim VarPath
VarFind = strFind
VarReplace = strReplace
VarPath = targetPath
Dim WshShell
Set WshShell = CreateObject("WScript.Shell")
WshShell.Run sScriptDir & "FindAndReplace.vbs /strfolderpath:" & VarPath
WshShell.Run sScriptDir & "FindAndReplace.vbs /strfind:" & VarPath
WshShell.Run sScriptDir & "FindAndReplace.vbs /strreplace:" & VarPath
FindAndReplace.vbs:
'Written by Terje Borchgrevink Nuis on 15.12.2014
Set objFSO = CreateObject("Scripting.FileSystemObject")
Dim strFind
Dim strReplace
Dim strFolderPath
strFolderPath = WScript.Arguments.Named("strfolderpath")
targetPath = strFolderPath
'Max number of times to replace string
strCount = 999
'Comparison type: 0 = case sensitive, 1 = case insensitive
strCompare = 1
If targetPath = "" Then
Wscript.Quit
End If
strFind = WScript.Arguments.Named("strfind")
If strFind = "" Then
Wscript.Quit
End If
strReplace = WScript.Arguments.Named("strreplace")
Set objFolder = objFSO.GetFolder(targetPath)
fileRename objFolder
Sub fileRename(folder)
Do
Wscript.sleep 10000
'Loop through the files in the folder
For Each objFile In folder.Files
filename = objFile.Name
ext = objFSO.getExtensionName(objFile)
safename = Left(filename, Len(filename) - Len(ext) - 1)
strStart = 1
safename = Replace(safename, strFind,strReplace,strStart,strCount,strCompare)
safename = trim(safename)
On Error Resume Next
'Terminate if filename stop.txt is found
If filename="STOP.txt" Then
result = MsgBox ("Are you sure you want to terminate the following VBScript?" & vbNewLine & vbNewLine & "FindAndReplace.vbs", vbOKCancel+vbSystemModal , "Terminate VBScript")
Select Case result
Case vbOK
WScript.quit
Case vbCancel
MsgBox "FindAndReplace.vbs is still running in the background.",,"Information"
End Select
End If
'Only rename if new name is different to original name
If filename <> safename & "." & ext Then
objFSO.MoveFile objFile.Path, objFile.ParentFolder.Path & "\" & safename & "." & ext
End If
If Err.Number <> 0 Then
WScript.Echo "Error renaming: " & filename.path & "Error: " & Err.Description
Err.Clear
End If
Next
Loop
End Sub
You think you want ConfigureFindAndReplace to change the other script, this is a bad idea.
You don't know it yet, but what you actually want is for FindAndReplace to read those items from a configuration file.
If the config file is well formed and easy to read, then your users can directly update the config file, so you may not even need the ConfigureFindAndReplace script.
How?
Have a text file with 3 lines
Target Folder=c:\DataFolder
String to find=a string
Replace with=Replace a string with this string
Then in FindAndReplace, before doing any work, you open this file and read in the three lines.
Split the lines on the '=' sign. The left half is the setting and the right half is the value.
Math these up to three variables in the script
If configLineLeft = "Target Folder" then REM Each of these should be case insensitive match
REM e.g. lcase(configLineLeft) = lcase("Target Folder")
TargetFolder = configLineRight
else if configLineLeft = "String to find" then
FindString = configLineRight
else if configLineLeft = "Replace with" then
ReplaceString = configLineRight
else
REM REPORT A PROBLEM TO THE USER AND EXIT
EXIT SUB
end if
You'd do the above in a while loop (while not end of file), reading each line and testing to see which setting it is.
As I can't find any VBScript in your .Zip, some general advice. If you want a not-to-be-edited script to do different things
let the script access parameters/arguments and specifying the differences by calling the script with different arguments: cscript FindAndReplace.vbs "c:\some\folder" "param" "arg"
let the script access config data (from a .txt, .ini, .xml, .json, ... file; from a database; from the registry; ...) and use the config script to set these data
use a template/placeholder file to generate (different version of) the script
I would start with the first approach.
After reading your edit:
Instead of calling your script trice with bad args:
WshShell.Run sScriptDir & "FindAndReplace.vbs /strfolderpath:" & VarPath
WshShell.Run sScriptDir & "FindAndReplace.vbs /strfind:" & VarPath
WshShell.Run sScriptDir & "FindAndReplace.vbs /strreplace:" & VarPath
execute it once with proper args:
WshShell.Run sScriptDir & "FindAndReplace.vbs /strfolderpath:" & VarPath & " /strfind:" & VarFind & "/strreplace:" & VarReplace
(untested; you need to check the names and take care of proper quoting; cf here)
Want to check if year is actual year in text file and update if not actual, 2013.
For example text line is: SET YEAR=2012
So far I have only been able to write actual year into file, but now I need to update the information in file if it exist...
Appreciating any help here.
dim filesys
Set filesys = CreateObject("Scripting.FileSystemObject")
path = filesys.GetAbsolutePathName("C:\Backups\Machine.bat")
getname = filesys.GetFileName(path)
If filesys.FileExists(path) Then
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set filesys = CreateObject("Scripting.FileSystemObject")
Set objFolder = objFSO.GetFile("C:\Backups\Machine.bat")
Set objFile = objFSO.OpenTextFile("C:\Backups\Machine.bat", 8)
objFile.WriteLine
objFile.Write("SET YEAR=")
objFile.WriteLine(Year(Date()))
objFile.Close
End if
You can replace a particular line in a text file like this:
path = "C:\Backups\Machine.bat"
Set fso = CreateObject("Scripting.FileSystemObject")
If fso.FileExists(path) Then
Set inFile = fso.OpenTextFile(path)
Set outFile = fso.OpenTextFile(path & ".tmp", 2, True)
Do Until inFile.AtEndOfStream
line = inFile.ReadLine
If UCase(Left(Trim(line), 9)) = "SET YEAR=" Then
outFile.WriteLine "SET YEAR=" & Year(Date)
Else
outFile.WriteLine line
End If
Loop
inFile.Close
outFile.Close
fso.DeleteFile path, True
fso.MoveFile path & ".tmp", path
End If