Solved

VBScript to Find list of files by ext, open the files and edit the txt on a line in the files

Posted on 2012-03-21
31
539 Views
Last Modified: 2012-06-27
I have a VBScript that will open up a file with .ws file extension, look for text that shows a path name, and replace with new text. What I need to do is a search of the entire hard drive for any files with this file extention and make this same change on them all. Can anyone please help?

Thanks
ReplaceTextTest4.vbs
0
Comment
Question by:jspade_69
  • 16
  • 13
  • 2
31 Comments
 
LVL 53

Expert Comment

by:Bill Prew
ID: 37750503
Give this a try, it should search all files in all subfolders.
Const ForReading = 1
Const ForWriting = 2

strFolder = "c:\"
strExtension = ".ws"

Set objFSO = CreateObject("Scripting.FileSystemObject")

DoFolder objFSO.GetFolder(strFolder)

Sub DoFolder(objFolder)
   For Each objFile in objFolder.Files
      If LCase(Right(objFile.Name, Len(strExtension))) = strExtension Then
         DoFile objFile
      End If
   Next

   For Each objSubFolder In objFolder.Subfolders
      DoFolder objSubFolder
   Next
End Sub

Sub DoFile(objFile)
   Set objFile = objFSO.OpenTextFile(objFile.Path, ForReading)

   strText = objFile.ReadAll
   objFile.Close

   strNewText = Replace(strText, "Program Files", "Program Files (x86)")

   Set objFile = objFSO.OpenTextFile(objFile.Path & strExtension, ForWriting)
   objFile.WriteLine strNewText
   objFile.Close
End Sub

Open in new window

~bp
0
 

Author Comment

by:jspade_69
ID: 37750579
Hey Bill Thanks for the reply....I ran the script and got the following error: Line 31, Char: 4, Error: Object doesn't support this property or method: 'objFile.Path', Code: 800A01B6
0
 
LVL 53

Expert Comment

by:Bill Prew
ID: 37750590
Sorry, missed that conflict between objFile and the code you had that I reused in that SUB.  This should take care of that.
Const ForReading = 1
Const ForWriting = 2

strFolder = "c:\"
strExtension = ".ws"

Set objFSO = CreateObject("Scripting.FileSystemObject")

DoFolder objFSO.GetFolder(strFolder)

Sub DoFolder(objFolder)
   For Each objFile in objFolder.Files
      If LCase(Right(objFile.Name, Len(strExtension))) = strExtension Then
         DoFile objFile
      End If
   Next

   For Each objSubFolder In objFolder.Subfolders
      DoFolder objSubFolder
   Next
End Sub

Sub DoFile(objFile)
   Set objRead = objFSO.OpenTextFile(objFile.Path, ForReading)

   strText = objRead.ReadAll
   objRead.Close

   strNewText = Replace(strText, "Program Files", "Program Files (x86)")

   Set objWrite = objFSO.OpenTextFile(objFile.Path & strExtension, ForWriting)
   objWrite.WriteLine strNewText
   objWrite.Close
End Sub

Open in new window

~bp
0
Master Your Team's Linux and Cloud Stack

Come see why top tech companies like Mailchimp and Media Temple use Linux Academy to build their employee training programs.

 

Author Comment

by:jspade_69
ID: 37750626
Different error now, same line and char, error is file not found
0
 
LVL 53

Expert Comment

by:Bill Prew
ID: 37750635
That looks like a bug in your original code, change this line:

   Set objWrite = objFSO.OpenTextFile(objFile.Path & strExtension, ForWriting)

to:

   Set objWrite = objFSO.OpenTextFile(objFile.Path & strExtension, ForWriting, True)

~bp
0
 
LVL 8

Expert Comment

by:Brent Challis
ID: 37750639
Here is a PowerShell solution.

The approach is to use the PowerShell cmdlet Get-ChildItem which has an alias of dir using the -recurse switch to indicate a need to trawl through the sub folders and only select *.ws files.  This collection of files is then piped into the cmdlet that I wrote at the beginning of the file that will test to see if the string you want to change is present it will then go through the lines in the file replacing the text and then outputting the new string in to a file of the original name with a .ws on the end.

function Replace-Text([string]$OriginalText,[string]$ReplacementText)
{
    Begin
    {
    }
    Process
    {
       
        if (([string](Get-Content $_.FullName)).IndexOf($OriginalText) -ge 0)
        {
            $content = Get-Content $_.FullName
            foreach ($line in $content)
            {
                $line.Replace($OriginalText,$ReplacementText) | Out-File ($_.FullName + ".ws") -append
            }
        }
    }
    End
    {
    }
}

dir -path C:\data\Development\Powershell\ScriptQuestion\ -include *.ws -recurse |
 Replace-Text "Program Files" "Program Files (x86)"
0
 

Author Comment

by:jspade_69
ID: 37750665
Bill error move to line 33 now, Invalid procedure call or argument
0
 
LVL 53

Expert Comment

by:Bill Prew
ID: 37750718
Is line 33 still:

objWrite.Close

if so, what else does the error message say exactly.

~bp
0
 

Author Comment

by:jspade_69
ID: 37750758
No line 33 is : objWrite.WriteLine strNewText, and the exact error message is Line 33, Char 4 Error: Invalid Procedure call or argument, Code: 800A0005
0
 
LVL 53

Expert Comment

by:Bill Prew
ID: 37750770
I don't see a problem with that statement, can you post up the exact script you are running.

~bp
0
 

Author Comment

by:jspade_69
ID: 37750800
Here you go
ReplaceTextTest6.vbs
0
 
LVL 53

Expert Comment

by:Bill Prew
ID: 37752022
I ran a test here and it worked fine.  You might want to add the following line at the beginning of the DoFile routine to see if any files are processed correctly, and which file it fails on:

Sub DoFile(objFile)
   Wscript.Echo objFile.Path

~bp
0
 

Author Comment

by:jspade_69
ID: 37755389
Hey Bill sorry it took me a while to test but I got more information.



I went back to the orginal code that you gave me and I added the Wscript.Echo objFile.Path as you suggested. I have a test.ws file on the root of C and a test2.ws file on the desktop.

1) The script echos the path for the file on the Root of "C" I click ok and then it echos the this path: C:\$Recycle.Bin\s-1-5-21-XXXXXXX\$I17NV4P.ws.ws. I click ok and then get Error message Line 27, Char 4, Error: INput past end of File, Code 800A003E.  I empty out the recycle bin and run again and it still echos the $Recycle.Bin path with the same error.

2) It does change the Text in the File that it sees on the root of "C" but it creates a new file and addes an additional ".ws" at the end (Test.ws.ws) and it never sees the one on the Desktop...I'm assuming that's because it stops after the error for path C:\$Recycle.Bin
ReplaceTextTest6.vbs
0
 
LVL 53

Expert Comment

by:Bill Prew
ID: 37755402
Ah, that makes some sense.  Trying to "use" files in the recycle bin could likely cause a number of different errors, as well as writing into that folder.  Would it make sense to add one or more folders like that to be skipped over in the code?

~bp
0
 

Author Comment

by:jspade_69
ID: 37755436
Bchallis,

Thanks for the response... I ran the powershell script and it did a couple of things:

1) it duplicated all the files as opposed to editing and saving the same file and added an extra ".ws" at the end changing the file name to "Test.ws.ws" and in one file it changed the Text to " "Program Files (x86) (x86" and another to "Program Files (x86) (x86) (x86)"
0
 

Author Comment

by:jspade_69
ID: 37755442
Bill that would make a lot of sense to skip those kinds of folders...I wouldn't need to check any hidden folders.
0
 
LVL 53

Expert Comment

by:Bill Prew
ID: 37755443
Okay, give this a try.
Const ForReading = 1
Const ForWriting = 2

strFolder = "c:\"
strExtension = ".ws"
arrOmit = Array("$RECYCLE.BIN","System Volume Information")

Set objFSO = CreateObject("Scripting.FileSystemObject")

DoFolder objFSO.GetFolder(strFolder)

Sub DoFolder(objFolder)
   Wscript.Echo "Processing folder=" & objFolder.Name
   For Each strOmit in arrOmit
      If LCase(strOmit) = objFolder.Name Then 
         Wscript.Echo "Skipping folder=" & objFolder.Name
         Exit Sub
      End If
   Next
   For Each objFile in objFolder.Files
      If LCase(Right(objFile.Name, Len(strExtension))) = strExtension Then
         DoFile objFile
      End If
   Next

   For Each objSubFolder In objFolder.Subfolders
      DoFolder objSubFolder
   Next
End Sub

Sub DoFile(objFile)
   Wscript.Echo "Processing file=" & objFile.Path
   Set objRead = objFSO.OpenTextFile(objFile.Path, ForReading)

   strText = objRead.ReadAll
   objRead.Close

   strNewText = Replace(strText, "Program Files", "Program Files (x86)")

   Set objWrite = objFSO.OpenTextFile(objFile.Path & strExtension, ForWriting, True)

   objWrite.WriteLine strNewText
   objWrite.Close
End Sub

Open in new window

~bp
0
 
LVL 53

Expert Comment

by:Bill Prew
ID: 37755462
Okay, this will skip all HIDDEN folders, as well as any in the arrOmit array.
Const ForReading = 1
Const ForWriting = 2

strFolder = "c:\"
strExtension = ".ws"
arrOmit = Array("$RECYCLE.BIN","System Volume Information")

Set objFSO = CreateObject("Scripting.FileSystemObject")

DoFolder objFSO.GetFolder(strFolder)

Sub DoFolder(objFolder)
   Wscript.Echo "Processing folder=" & objFolder.Name
   If objFolder.Attributes AND 2 Then
      Wscript.Echo "Skipping hidden folder=" & objFolder.Name
      Exit Sub
   End If
   For Each strOmit in arrOmit
      If LCase(strOmit) = objFolder.Name Then 
         Wscript.Echo "Skipping omitted folder=" & objFolder.Name
         Exit Sub
      End If
   Next
   For Each objFile in objFolder.Files
      If LCase(Right(objFile.Name, Len(strExtension))) = strExtension Then
         DoFile objFile
      End If
   Next

   For Each objSubFolder In objFolder.Subfolders
      DoFolder objSubFolder
   Next
End Sub

Sub DoFile(objFile)
   Wscript.Echo "Processing file=" & objFile.Path
   Set objRead = objFSO.OpenTextFile(objFile.Path, ForReading)

   strText = objRead.ReadAll
   objRead.Close

   strNewText = Replace(strText, "Program Files", "Program Files (x86)")

   Set objWrite = objFSO.OpenTextFile(objFile.Path & strExtension, ForWriting, True)

   objWrite.WriteLine strNewText
   objWrite.Close
End Sub

Open in new window

~bp
0
 

Author Comment

by:jspade_69
ID: 37755474
BP

That new code states:

1. Processing Folder=    click ok
2. Processing File= c:\test.ws    click ok
3. Processing Folder= $recycle.bin
4. Processing folder=s-1-5-21-xxxxxx
5. Processing File= C:\$Recycle.Bin\s-1-5-21-xxxxxxx\SI17NV4P.ws.ws

And then the same Line 35, char 4 Input past end of life error
0
 
LVL 8

Expert Comment

by:Brent Challis
ID: 37755478
The reason that I added the extension to the file name was that your sample code had:
     Set objFile = objFSO.OpenTextFile("C:\TestTextFile.ws.ws", ForWriting)
so I emulated that.

On ethe basis that you want to update the existing file, replacing the body of the foreach loop in the Process section with:
{
            $content = Get-Content $_.FullName
            foreach ($line in $content)
            {
                $line.Replace($OriginalText,$ReplacementText) | Out-File ($_.FullName + ".tmp") -append
            }
            Remove-Item $_.FullName
            Rename-Item -path ($_.FullName + ".tmp") -NewName $_.FullName
        }
should work.
0
 
LVL 53

Expert Comment

by:Bill Prew
ID: 37755507
Well, I would expect the recycle bin to be hidden, but I see a bug in the omit logic so let's try this:
Const ForReading = 1
Const ForWriting = 2

strFolder = "c:\"
strExtension = ".ws"
arrOmit = Array("$RECYCLE.BIN","System Volume Information")

Set objFSO = CreateObject("Scripting.FileSystemObject")

DoFolder objFSO.GetFolder(strFolder)

Sub DoFolder(objFolder)
   Wscript.Echo "Processing folder=" & objFolder.Name
   If objFolder.Attributes AND 2 Then
      Wscript.Echo "Skipping hidden folder=" & objFolder.Name
      Exit Sub
   End If
   For Each strOmit in arrOmit
      If LCase(strOmit) = LCase(objFolder.Name) Then 
         Wscript.Echo "Skipping omitted folder=" & objFolder.Name
         Exit Sub
      End If
   Next
   For Each objFile in objFolder.Files
      If LCase(Right(objFile.Name, Len(strExtension))) = strExtension Then
         DoFile objFile
      End If
   Next

   For Each objSubFolder In objFolder.Subfolders
      DoFolder objSubFolder
   Next
End Sub

Sub DoFile(objFile)
   Wscript.Echo "Processing file=" & objFile.Path
   Set objRead = objFSO.OpenTextFile(objFile.Path, ForReading)

   strText = objRead.ReadAll
   objRead.Close

   strNewText = Replace(strText, "Program Files", "Program Files (x86)")

   Set objWrite = objFSO.OpenTextFile(objFile.Path & strExtension, ForWriting, True)

   objWrite.WriteLine strNewText
   objWrite.Close
End Sub

Open in new window

~bp
0
 

Author Comment

by:jspade_69
ID: 37755568
BP

now I have

1: Processing Folder=     Click ok
2: Skipping hidden folder=  click ok


and nothing else...I don't think it's processing the other folders now

I tried to compare this last code with the previous and I couldn't find the error...LOL I was hope that I could impression by say Ahh I found the issue but sorry I couldn't. LOL

At least it's not processsing the $Recycle.bin now and generating an error.
0
 
LVL 53

Accepted Solution

by:
Bill Prew earned 500 total points
ID: 37755625
Okay, I guess C:\ is indeed a hidden folder, so we have to not skip that one, argh.

Also, if you run this from a command line like this you won't have to press enter on every dsplay message:

cscript EE27643183.vbs
Const ForReading = 1
Const ForWriting = 2

strFolder = "c:\"
strExtension = ".ws"
arrOmit = Array("$RECYCLE.BIN","System Volume Information")

Set objFSO = CreateObject("Scripting.FileSystemObject")

DoFolder objFSO.GetFolder(strFolder)

Sub DoFolder(objFolder)
   Wscript.Echo "Processing folder=" & objFolder.Name
   If objFolder.Name <> "" Then 
      If objFolder.Attributes AND 2 Then
         Wscript.Echo "Skipping hidden folder=" & objFolder.Name
         Exit Sub
      End If
   End If
   For Each strOmit in arrOmit
      If LCase(strOmit) = LCase(objFolder.Name) Then 
         Wscript.Echo "Skipping omitted folder=" & objFolder.Name
         Exit Sub
      End If
   Next
   For Each objFile in objFolder.Files
      If LCase(Right(objFile.Name, Len(strExtension))) = strExtension Then
         DoFile objFile
      End If
   Next

   For Each objSubFolder In objFolder.Subfolders
      DoFolder objSubFolder
   Next
End Sub

Sub DoFile(objFile)
   Wscript.Echo "Processing file=" & objFile.Path
   Set objRead = objFSO.OpenTextFile(objFile.Path, ForReading)

   strText = objRead.ReadAll
   objRead.Close

   strNewText = Replace(strText, "Program Files", "Program Files (x86)")

   Set objWrite = objFSO.OpenTextFile(objFile.Path & strExtension, ForWriting, True)

   objWrite.WriteLine strNewText
   objWrite.Close
End Sub

Open in new window

~bp
0
 

Author Comment

by:jspade_69
ID: 37755660
BP,

That ran through with no problem and I had files in three different places and it change the text on the 3 files in the 3 different locationa, but one last thing...instead of editing the existing file and saving it, it created a new file in each location  adding an extra .ws at the end...example the test.ws file on the root of C was changed and save as test.ws.ws, and the test2.ws file on the desktop was changed as saved as test2.ws.ws
0
 
LVL 53

Expert Comment

by:Bill Prew
ID: 37755669
Yes, that came out of your original code sample I believe.  So you want it to overwrite the existing file?

~bp
0
 

Author Comment

by:jspade_69
ID: 37755678
Yes sir
0
 

Author Comment

by:jspade_69
ID: 37755686
BP

Line 42 Set objWrite = objFSO.OpenTextFile(objFile.Path & strExtension, ForWriting, True)


I removed the "& strExtension"    and it work!!!! it made the change to the original file and save it.
0
 

Author Comment

by:jspade_69
ID: 37755697
BP Thanks for the great help and the great patients.
0
 

Author Comment

by:jspade_69
ID: 37755709
BChallis,

I'm going to keep playing with the powershell option as well to see if I can get it wor work.  this is the new file with the new changes you gave me but it barked at me

CategoryInfo          : ParserError: (}:String) [], ParseException
FullyQualifiedErrorId : UnexpectedToken

maybe I didn't added the change properly....less formiliar with powershell.

function Replace-Text([string]$OriginalText,[string]$ReplacementText)
{
    Begin
    {
    }
    Process
    {
            $content = Get-Content $_.FullName
            foreach ($line in $content)
            {
                $line.Replace($OriginalText,$ReplacementText) | Out-File ($_.FullName + ".tmp") -append
            }
            Remove-Item $_.FullName
            Rename-Item -path ($_.FullName + ".tmp") -NewName $_.FullName
        }

        }
    }
    End
    {
    }
}

dir -path C:\ -include *.ws -recurse |
 Replace-Text "Program Files" "Program Files (x86)"
0
 

Author Closing Comment

by:jspade_69
ID: 37755713
BP is amazing in how quickly he responded and how accurate his solution was.
0
 
LVL 53

Expert Comment

by:Bill Prew
ID: 37756523
Good morning, glad to see you got where you wanted to be and that I was able to help.  Thanks for the feedback.

~bp
0

Featured Post

Netscaler Common Configuration How To guides

If you use NetScaler you will want to see these guides. The NetScaler How To Guides show administrators how to get NetScaler up and configured by providing instructions for common scenarios and some not so common ones.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Microsoft Windows Server Update Service (WSUS) is free for everyone, but it lacks of some desirable features like send an e-mail to the administrator with the status of all computers on the WSUS server. This article is based on my PowerShell script …
This article will help you understand what HashTables are and how to use them in PowerShell.
Learn the basics of while and for loops in Python.  while loops are used for testing while, or until, a condition is met: The structure of a while loop is as follows:     while <condition>:         do something         repeate: The break statement m…
This tutorial will teach you the core code needed to finalize the addition of a watermark to your image. The viewer will use a small PHP class to learn and create a watermark.

777 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question