Loic
Loic

Reputation: 123

Replace a specific string with the filename?

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

Upvotes: 1

Views: 354

Answers (1)

peter
peter

Reputation: 42192

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) }

Upvotes: 1

Related Questions