Replace some text in each single file inside subfolders - vbscript

I have around 30 subfolders(each folder consists many subfolders) in a folder.I am trying to replace some text form each sql file.I have written some code to this in vbscript and test it with 3-4 subfolders and it was working perfectly.But when i am trying to run it with all the folders, the files are not getting written.
'Root path where all folders and files are present
'Change according to your requirement
strPath="W:\New Folder\Test1"
Set objFso = CreateObject("Scripting.FileSystemObject")
'To access folders
Set objFolder = objFso.GetFolder (strPath)
TraverseFolder (objFso.GetFolder(strPath))
Function TraverseFolder(FolderName)
For Each fld in FolderName.SubFolders
TraverseFolder(fld)
For Each flname in fld.Files
if objFso.GetExtensionName(flname.Path)="sql" then
'msgbox fld.Path & "\" & objFso.GetFileName(flname.Path)
'After commenting whole below section,and running rest of code with
'the above mentioned msgbox every single folder and files are getting
'fetched but when i uncomment below section, only some folders and
'files are getting displayed in msgbox'
Const ForReading = 1
Const ForWriting = 2
Set objFile = objFso.OpenTextFile(fld.Path & "\" & objFso.GetFileName(flname.Path), 1)
strText = objFile.ReadAll
objFile.Close
strText= Replace(strText, "A_", "L_")
strText= Replace(strText, "A", "D")
strText= Replace(strText, "Database\Sy", "Database\SQ")
Set objFile = objFso.OpenTextFile(fld.Path & "\" & objFso.GetFileName(flname.Path), 2)
objFile.WriteLine strText
objFile.Close
End If
Next
Next
End Function

It seems to me that you are not using ForReading and ForWriting constants anyway(in the code you posted). Just delete them.

Related

Saving file into another file using VBScript after modification

I have some XML files in a folder \\demo.US\Modified\. The files in the folder are:
USA.xml
Canada.xml
Mexico.xml
The code below is changing the encoding from UTF-8 to windows-1252 and is creating a modified file mod.xml.
This mod.xml file have data from all three XML files concatenated.
I need help so I can save files separately.
If value of objFile.Name is USA.xml then it should save modified file name as USA_mod.xml. the output for \\demo.US\Modified\ folder after execution is complete should have mod files in it as below.
USA.xml
Canada.xml
Mexico.xml
USA_mod.xml
Canada_mod.xml
Mexico_mod.xml
The code I used is as follows.
Set objFSO = CreateObject("Scripting.FileSystemObject")
objStartFolder = "\\demo.US\Modified\"
Set objFolder = objFSO.GetFolder(objStartFolder)
Set colFiles = objFolder.Files
For Each objFile In colFiles
WScript.Echo objFile.Name
Set objFile = objFSO.OpenTextFile(objStartFolder & objFile.Name, 1)
Set outFile = objFSO.OpenTextFile(objStartFolder & "mod.xml", 2, True)
Do Until objFile.AtEndOfStream
strContent = strContent & objFile.ReadLine
Loop
MsgBox strContent
strContent = Replace(strContent, "encoding=""UTF-8""", "encoding=""windows-1252""")
outFile.WriteLine strContent
outFile.Close
objFile.Close
Next
As others have already pointed out, you shouldn't do what you're attempting to do here, because it is very likely to create more problems down the road. Find the cause of the issue and fix that instead of trying to handle symptoms. You have been warned.
With that said, the reason why the content of all input files is written to the same output file is because you always specify the same output file. That file should contain only the content of the last input file, though, because you open the file for writing (thus erasing previous content) rather than for appending.
Replace these lines:
Set objFile = objFSO.OpenTextFile(objStartFolder & objFile.Name, 1)
Set outFile = objFSO.OpenTextFile(objStartFolder & "mod.xml", 2, True)
with this:
Set inFile = objFile.OpenAsTextStream
outFilename = objFSO.BuildPath(objStartFolder, objFSO.GetBaseName(objFile) & "_mod.xml")
Set outFile = objFSO.OpenTextFile(outFilename, 2, True)
and also replace the other occurrences of objFile after that with inFile (always avoid changing the value of a loop variable), and the code should do what you expect it to do. But again, be warned that the output may not be valid XML.
I managed to made it working, below is the code I used
Dim objFSO, filePath, objFile, colFiles, s , FName
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set filePath = objFSO.GetFolder("\\demo.US\Modified\")
Set colFiles = filePath.Files
For Each FName in colFiles
set objFile = objFSO.OpenTextFile(FName.Path,1)
set outFile = objFSO.OpenTextFile(LEFT(FName.Path,instr(FName.Path,".xml")-1) &"_mod.xml",2,True)
do until objFile.AtEndOfStream
strContent=objFile.ReadLine
Loop
strContent = Replace(strContent, "encoding=""UTF-8""", "encoding=""windows-1252""")
outFile.WriteLine strContent
outFile.Close
objFile.Close
Next

Faster method to copy file

I am trying to copy file using following script.
Option Explicit
Const ForWriting = 2
Dim objFSO
Dim desfolder
Dim oShell
dim s
desfolder = "D:\Databases"
Set objFSO = CreateObject("Scripting.FileSystemObject")
Recurse objFSO.GetFolder("D:\Databases\Images")
Sub Recurse(objFolder)
Dim objFile, objSubFolder
For Each objFile In objFolder.Files
If LCase(objFSO.GetExtensionName(objFile.Name)) = "tif" Then
s = Right(objFile.Name, 10)
S = Left(s, 1)
If Left(s, 1) = "C" Then
Set oShell = WScript.CreateObject("WScript.Shell")
oShell.Run "xcopy.exe " & objFile & " " & desfolder & " /R /Y", _
0, True
End If
End If
Next
For Each objSubFolder In objFolder.SubFolders
Recurse objSubFolder
Next
End Sub
What I am trying to do is checking files in folders and subfolders. If file is tif then checking weather it contains required letter "C" at specific position. and using xcopy to copy the file.
It works fine but is very slow.
Is there any faster method to do this?
Edit: What I want exactly is to find c*.tif in a folder and its subfolders.
Don't use xcopy then. Doing it your way spawns a new process each time you copy a file. Just use the file object's Copy method and be done with it.
Sub Recurse(objFolder)
Dim objFile, objSubFolder
For Each objFile In objFolder.Files
If LCase(objFSO.GetExtensionName(objFile)) = "tif" Then
If LCase(Left(objFile.Name, 1) = "c" Then
objFile.Copy desfolder & "\"
End If
End If
Next
For Each objSubFolder In objFolder.SubFolders
Recurse objSubFolder
Next
End Sub
Note that your destination path requires a trailing backslash because it's a folder (you'd get a "permission denied" error without it). Otherwise you need to specify the destination path including the filename, e.g. like this:
objFile.Copy objFSO.BuildPath(desfolder, objFile.Name)

Too many iterations in loop

This script collects all files in a folder and renames the files by appending the number of lines to the file name. All files are .txt files. The method (since fso.MoveFile and fso.DeleteFile are too particular, generating permissions errors) is to
create the text files,
then create a collection of the files in the folder,
then copy each file into the same folder with a new name, and
finally to delete the original file that was copied.
The script works ok, unless there are no empty text files in the collection. What happens is, the collection gets rebuilt with the new files and the script once again renames the files. I know I can prevent this by checking each file for the existence of certain repeating character strings, but I'd like to know what's happening? Why does the script rebuild the file collection and run through them again renaming each one? This continues on until I kill the process.
Another interesting factoid is, if I happen to trap an empty text file, my message is displayed and the script stops there, but has still reprocessed the first file in the collection a second time. Note that the empty file just happens to be the last one in the collection, but the first filed is once again processed.
So, by design a created text file named 'ab0.txt' gets renamed to 'ab0-15.txt' since it has 15 lines of text in it. What happens is this newly renamed file looks like 'ab0-15-15-15-15-15-15-15-15-15-15.txt'
Questions: What's going on? And is there a better and more efficient way to accomplish this objective?
Here's the code pertinent to the issue:
Set fso = CreateObject("Scripting.FileSystemObject")
Set oFolder = fso.GetFolder(strSaveTo)
Set colFiles = oFolder.Files
' Call Sub to copy and rename
ChangeFileName colFiles
MsgBox("File renaming complete.")
' Exit code
Sub ChangeFileName(collectionSet)
Const ForReading = 1
Dim oFile
For Each oFile In collectionSet
Set LineCnt = fso.OpenTextFile(oFile, ForReading)
If oFile.Size = 0 then
'if this msg is not included, weird things happen
MsgBox("The file named " & oFile & _
" is empty.You may want to verify and manually delete it.")
'[I had some code in here to delete the empty file, but nothing worked]
Else
Do While LineCnt.AtEndOfStream <> True
LineCnt.SkipLine
Loop
lineVar = lineCnt.Line-1
strNewFile = strSaveTo & Left(oFile.name, Len(oFile.name)-4) & _
"-" & lineVar & ".txt"
fso.CopyFile oFile, strNewFile
LineCnt.Close
fso.DeleteFile oFile, True
End If
Next
End Sub
I've heard anecdotal evidence that the Files collection is "live", meaning that newly created files will be added to the collection and iterated over, but I can't find any documentation that says one way or the other. In any case, it's probably a good idea to copy the File objects in the collection to an array first before processing them:
Dim oFile
Dim fileArray()
Dim i
ReDim fileArray(collectionSet - 1)
i = 0
For Each oFile in collectionSet
Set fileArray(i) = oFile
i = i + 1
Next
For Each oFile In fileArray
' Count lines and rename
Next
It seems that collectionSet is the collection of files in the folder that you are trying to modify. The problem is that with each pass through the for-each loop you are adding files to this folder, some of which are fed back into the loop. What you need to do is the find a way to take a snapshot of the folder before you try to iterate over it. The way to do this would be to replace the folder collectionSet by a collection of strings which are the names of the files before you iterate over it, and modify your code to open the files by their name (instead of via a file object). That way the collection won't be expanding while you iterate over it.
You should create your vars in the scope they are used (e.g. your
file/folder objects are used in the sub.
Always explicit(ly) declare your vars.
You don't need to copy the file and rename it then do the delete.
Just rename it with the FileObject.Name property.
Here is an example:
Option Explicit 'always declare your vars!
Dim strFolder: strFolder = "c:\temp\Rename Test"
Dim strExtension: strExtension = "txt"
' Call Sub to rename the files in the folder
ChangeFileName strFolder, strExtension
Sub ChangeFileName(strFolder, strExtension)
Const ForReading = 1
Dim FSO: set FSO = CreateObject("Scripting.FileSystemObject")
Dim objFolder: set objFolder = FSO.GetFolder(strFolder)
Dim colFiles: set colFiles = objFolder.Files
Dim objFile
Dim intCount
Dim strFileName
Dim objTextStream
For Each objFile In colFiles
msgbox "File: " & objfile.path & vbcrlf & FSO.GetExtensionName(objFile.path)
if UCase(FSO.GetExtensionName(objFile.Path)) = UCase(strExtension) and _
objFile.Size > 0 then
'set LineCnt = FSO.OpenTextFile(objFile, ForReading)
set objTextStream = objFile.OpenAsTextStream(ForReading,-2)
intCount = 0
strFileName = objFile.Name
Do While objTextStream.AtEndOfStream <> True
intCount = intCount + 1
objTextStream.ReadLine
Loop
objTextStream.Close
objFile.Name = FSO.GetBaseName(objFile.Path) & "-" & _
intCount & "." & FSO.GetExtensionName(objFile.Path)
end if
Next
End Sub

vbscript to delete files & folders of remote computer

First thing I am not an expert in writing VBScripts.
I have a requirement of deleting files & folders of remote systems with just 1 click. I was trying to build below VBScript but somehow it’s not working. I request any of your help to correct the same or with a new script that help me to fulfill the requirement. Any help in this regard is greatly appreciated, Thanks in Advance.
With the below:
C:\Test - is the directory from where I would like to delete the files & subfolders
C:\computerList.txt – is the text file contains all remote systems IP Address.
Const strPath = "C:\Test"
Set computerList = objfso.OpenTextFile ("C:\computerList.txt", 1)
Dim objFSO
Set objFSO = CreateObject("Scripting.FileSystemObject")
Call Search (strPath)
WScript.Echo"Done."
Sub Search(str)
Do While Not computerList.AtEndOfStream
strComputer = computerList.ReadLine
Dim objFolder, objSubFolder, objFile
Set objFolder = objFSO.GetFolder("\\" & strComputer & "\" & str)
For Each objFile In objFolder.Files
If objFile.DateLastModified < (Now() - 0) Then
objFile.Delete(True)
End If
Next
For Each objSubFolder In objFolder.SubFolders
Search(objSubFolder.Path)
' Files have been deleted, now see if
' the folder is empty.
If (objSubFolder.Files.Count = 0) Then
objSubFolder.Delete True
End If
Next
loop
End Sub
Regards,
Balaram Reddy
Your first problem is that you have the line order incorrect:
Set computerList = objfso.OpenTextFile ("C:\computerList.txt", 1)
Dim objFSO
Set objFSO = CreateObject("Scripting.FileSystemObject")
Should be
Dim objFSO
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set computerList = objfso.OpenTextFile ("C:\computerList.txt", 1)
You are using objfso before declaring it
When using a UNC path, you will need to use the folder's remote share name. If you have admin privileges on the remote pc use:
Const strPath = "c$\Test"

SFTP transfer file and move file to folder

This is my first post so please excuse my ignorance. I am using a vbscript to zip all .csv type files in a particular folder. After some google searches, I have found a workable vbscript to do this and have enabled a scheduled task to automate this.
What I need to do next is to transfer the zip file via sftp and then "move" that zip file into another folder. I believe the former can be achieved using pscp.exe via command line but can someone show me how to do the latter?
Basically the zipping will be done twice a day and so it will have a timestamp similar to yyyymmdd0900.zip (for 9am schedule) and yyyymmdd1800.zip (for 6pm schedule). After the transfer, I want to move (not copy) the zip file generated into another folder.
Any pointers would be greatly appreciated. Thank you all in advance.
EDIT: Here is some code I slapped together based on some Google searches. It does what I want it to do. Please excuse the "pasting" as i couldn't figure out how to format it properly. Currently, it runs the bat file after copying but I just noticed that i need to send (using PuTTY Secure Copy) the "latest" zip file before moving it to the "completed" folder. Can someone please show me how to do this?
Zipping the file and rename the zip file
My Code :
On Error Resume Next
strFilepath = "c:\files"
strDestination = "c:\files\completed\"
strExtension = "csv"
strYear = Year(Now)
strMonth = Right("0" & Month(Now), 2)
strDay = Right("0" & Day(Now), 2)
strHour = Right ("0" & Hour(Now), 2)
strMinute = Right ("0" & Minute (Now), 2)
strZip = strFilepath & "\" & strYear & strMonth & strDay & strHour & strMinute & ".zip"
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFolder = objFSO.GetFolder(strFilepath)
For Each objFile in objFolder.Files
strFileExt = objFSO.GetExtensionName(objFile.Path)
If LCase(strFileExt) = LCase(strExtension) Then
ZipFile objFile.Path, strZip
End If
Next
Sub ZipFile(strFileToZip, strArchive)
Set objFSO = CreateObject("Scripting.FileSystemObject")
If Not objFSO.FileExists(strArchive) Then
Set objTxt = objFSO.CreateTextFile(strArchive)
objTxt.Write "PK" & Chr(5) & Chr(6) & String(18, Chr(0))
objTxt.Close
End If
Set objApp = CreateObject( "Shell.Application" )
intCount = objApp.NameSpace(strArchive).Items.Count + 1
objApp.NameSpace(strArchive).CopyHere strFileToZip
Do
WScript.Sleep 200
set objNameSpace = objApp.NameSpace(strArchive)
If Not objNameSpace is nothing Then
If objNameSpace.Items.Count = intCount Then
Exit Do
End If
End If
Loop
End Sub
>Move file to a different folder and then run a bat file to secury copy file to a FTP location
'Vars
Dim objFSO, objFileCopy, objFileDelete, dot, files, file
Dim strDestination, folder, subfolder, fileCount, strFilePath
'Strings
strDestination = "C:\Files\Completed\"
strFilePath = "C:\Files"
set objFSO = CreateObject("Scripting.fileSystemObject")
set folder = objFSO.getFolder(strFilePath)
For Each file In folder.files
Set objFileCopy = objFSO.GetFile(file)
If objFSO.GetExtensionName(file) = "zip" Then
objFSO.MoveFile objFileCopy.Path, strDestination
End If
Next
Dim shell
Set shell=createobject("wscript.shell")
Shell.run "C:\testsend.bat"
Set shell=nothing
This will move a file to the specified location.
Sub Move_File(Source_File, Destination_Folder)
Dim fso
Set fso = CreateObject("Scripting.FileSystemObject")
fso.MoveFile Source_File, Destination_Folder
Set fso = Nothing
End Sub
sftp client provides a means to change working directory on the host before performing any file transfers. It would be better to thus transfer the file directly to the target location.
NOTE: The above answer was a result of misunderstanding the question. I read it to mean the file had to be moved on the destination but the real operation was to move the file on the origin.
I found the following example code that moves a file after checking that it exists. Wildcards are allowed for the source parameter but then FileExists may not work. Requires vbscript 2.0 to work.
<%
dim filesys
set filesys=CreateObject("Scripting.FileSystemObject")
If filesys.FileExists("c:\sourcefolder\anyfile.html") Then
filesys.MoveFile "c:\sourcefolder\anyfile.html", "c:\destfolder\"
End If
%>

Resources