Search Keyword and rename entire file using VBS - vbscript

I spent a quite a bit looking around. I did find one method that was extremely close to what I was looking for but it replaces keywords.
Dim sName
Dim fso
Dim fol
' create the filesystem object
Set fso = WScript.CreateObject("Scripting.FileSystemObject")
' get current folder
Set fol = fso.GetFolder("F:\Downloads")
' go thru each files in the folder
For Each fil In fol.Files
' check if the file name contains underscore
If InStr(1, fil.Name, "[wizardry] tv show bob - 13") <> 0 Then
' replace underscore with space
sName = Replace(fil.Name, "[wizardry] tv show bob - 13", "tv show bob S03E13")
' rename the file
fil.Name = sName
End If
Next
' echo the job is completed
WScript.Echo "Completed!"
But as I said, the only issue is that it repalces the keywords. I want it to replace the ENTIRE file name with what I want.
Most of the files will have a group tag before hand like this: [wizardy] tv show bob - 13
I want to make sure the group tag is gone so I can actually copy the file over. Unless there is a way to pull the file name of the current file I renamed.
Any help is appreciated, thanks.

Instead of replace, you need to generate a new name with the original extension, I think? If not, please give us more detail.
Dim sName
Dim fso
Dim fol
Dim fil
Dim ext
Set fso = WScript.CreateObject("Scripting.FileSystemObject")
Set fol = fso.GetFolder("F:\Downloads")
For Each fil In fol.Files
'may need to specify a comparison
If InStr(1, fil.Name, "[wizardry] tv show bob - 13", vbTextCompare) <> 0 Then
ext = fso.GetExtensionName(fil)
If Len(ext) > 0 Then ext = "." & ext
sName = "tv show bob S03E13" & ext
fil.Name = sName
End If
Next
WScript.Echo "Completed!"

Related

VBS Script that will execute on all subfolders

Update-----
My vbs script should take camera photos and rename them from a unique name like "0634_IMG" to a recursive number from 01 to 100. For example say there are 3 photos in the folder: 001_IMG, 003_IMG, and 006_IMG my script should rename these files to 01, 02, and 03 respectively.
I have a version that works when I drag and drop the script into the specific folder, but there are 1000's of folders so I want to be able to place it into the parent folder and it execute on all subfolders.
So it should be a folder drill down that only looks for files with the extension GIF, IMG, and PNG.
Folder Structure: Location>Block#>Letter(comprised of 3 folders A, B, and C)>Chamber(for each letter there are 4 subfolders)>Pictures (each subfolder has the pictures I am trying to rename)
so to review, I want to be able to put the script in the same folder as the block# and it execute on the pictures in the last folder for every subfolder. So after I run the script each picture should be renamed 01-100 and maintain its position within the folder scheme.
Thanks to the help of CHNguyen, my code was edited so that it would maintain the folder structure I describe above.
The issue now is that the script is numbering the pictures in every folder continuously and does not start or restart at 1.... For example after executing the script, Folder 1 (which contains 30 images) is outputting file names 830-860, when it should be 1-30. Additionally, the other subfolders have this same issue and it seems that the count or "intFileParts" is not being reset and I can't get it to reset.
I ask the coding gods for help as I am a newb and thanks in advance.
Option Explicit
Dim fso
Dim oFolder, oSubFolder
Dim oFile
Dim sPath, strOldName, strNewName
Dim intFileParts
' Create the instance of the fso.
Set fso = CreateObject("Scripting.FileSystemObject")
' Set the folder you want to search.
sPath = fso.GetFolder(fso.GetAbsolutePathName(".")) + "\"
RenameFiles(sPath)
Sub RenameFiles(Path)
Set oFolder = fso.GetFolder(Path)
intFileParts = 1 ' Restart at 1
' Loop through each file in the folder.
For Each oFile In oFolder.Files
' Only select images
Select Case oFile.Type
Case "GIF Image", "JPG Image", "PNG Image"
End Select
' Get complete file name with path.
strOldName = oFile.Path
' Build the new file name.
strNewName = ""
strNewName = fso.GetParentFolderName(oFile) & "\" & Right("000" & fso.GetBaseName(oFile), 3) & "." & fso.GetExtensionName(oFile)
' Use the MoveFile method to rename the file.
fso.MoveFile strOldName, strNewName
intFileParts = intFileParts + 1
Next
For Each oSubFolder In oFolder.Subfolders
RenameFiles(oSubFolder.Path)
Next
End Sub
Set oFile = Nothing
Set oSubFolder = Nothing
Set oFolder = Nothing
Set fso = Nothing
This should do:
I reworked the ' Build the new file name. section to properly get the file's parent folder using fso.GetParentFolderName() to "maintain its position within the folder scheme". The padding and incrementing of the numeric value in the filename was also improved/simplified using VB and fso methods.
The "missing" code under ' Use the MoveFile method to rename the file. was also added to perform the rename via fso.MoveFile()
Code:
Option Explicit
Dim fso
Dim oFolder, oSubFolder
Dim oFile
Dim sPath, strOldName, strNewName
Dim intFileParts
' Create the instance of the fso.
Set fso = CreateObject("Scripting.FileSystemObject")
' Set the folder you want to search.
sPath = fso.GetFolder(fso.GetAbsolutePathName(".")) + "\"
RenameFiles(sPath)
Sub RenameFiles(Path)
Set oFolder = fso.GetFolder(Path)
intFileParts = 1 ' Restart at 1
' Loop through each file in the folder.
For Each oFile In oFolder.Files
' Only select images
Select Case oFile.Type
Case "GIF Image", "JPG Image", "PNG Image"
End Select
' Get complete file name with path.
strOldName = oFile.Path
' Build the new file name.
strNewName = ""
strNewName = fso.GetParentFolderName(oFile) & "\" & Right("000" & intFileParts, 3) & "." & fso.GetExtensionName(oFile)
' Use the MoveFile method to rename the file.
fso.MoveFile(strOldName, strNewName)
intFileParts = intFileParts + 1
Next
For Each oSubFolder In oFolder.Subfolders
RenameFiles(oSubFolder.Path)
Next
End Sub
Set oFile = Nothing
Set oSubFolder = Nothing
Set oFolder = Nothing
Set fso = Nothing

Look for a word within the folder name with VB scripting

How can i read a folder name with vb script and look for a particular word?
EG:
Folder name = 1234abc_Complete
How can i get the text complete and store as a variable?
Thank you!
The following code should do as you require.
Option Explicit
' create a FileSystemObject
Dim oFso : Set oFso = CreateObject("Scripting.FileSystemObject")
' Set a reference to the folder which contains the folders you want to look through
Dim oFolder : Set oFolder = oFso.GetFolder("PathToFolderInHere")
Dim oSubFolder, myVar
' loop through each subfolder
For Each oSubFolder in oFolder.SubFolders
' If the oSubFolder contains the word complete then set myVar and exit the loop
If InStr(1, oSubFolder.Name, "complete", vbTextCompare) > 0 Then
myVar = oSubFolder.Name
Exit For
End If
Next
' do whatever with myVar (the folder name you wanted in the variable).

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

Copy File Over, then rename VBS

So, I had a user help me out in getting the file renamed, which is fantastic!
Here is the code:
Set fso = WScript.CreateObject("Scripting.FileSystemObject")
Set fol = fso.GetFolder("F:\Downloads")
For Each fil In fol.Files
'may need to specify a comparison
If InStr(1, fil.Name, "tv show bob - 13", vbTextCompare) <> 0 Then
ext = fso.GetExtensionName(fil)
If Len(ext) > 0 Then ext = "." & ext
sName = "tv show bob S03E13" & ext
fil.Name = sName
End If
Next
WScript.Echo "Completed!"
But the issue I come across now is that the file is being used by a torrent program. Right now, for the standard files I use this line of code:
If (objFSO.FileExists("D:\TV Shows\tv\tv show S01E02.mkv")) Then
Else
objFSO.CopyFile "D:\Downloads\tv show - 02 [1080p].mkv", "D:\TV Shows\tv\tv show S01E02.mkv"
End If
I was wondering if it possible to have it copy the file, then paste the renamed version using the first section of the code. Thanks for your help :D

Find and replace multiple file in vbs

I am trying to implement a find and replace for all files in a folder using a vbs script, here is what I have so far
Dim fso,folder,files,oldFileContents,newFileContents,FIND,REPLACE
FIND = "textToBeReplaced"
REPLACE = "localhost"
Set fso = CreateObject("Scripting.FileSystemObject")
Set folder = fso.GetFolder("HTML")
Set files = folder.Files
For each item In files
oldFileContents = GetFile(item.Path)
newFileContents = replace(oldFileContents,FIND,REPLACE,1,-1,1)
WriteFile FileName,newFileContents
Next
but when I try to run it I get and error, "Type Mismatch: 'GetFile'", what am I doing wrong?
The problem should be solved with code like:
' Constants Mr Gates forgot (but cf. vbTextCompare)
Const ForReading = 1
Const ForWriting = 2
' Configuration constants
Const csFind = "pdf"
Const csRepl = "puf"
' Dim & init for vars needed on *this* level
Dim oFS : Set oFS = CreateObject("Scripting.FileSystemObject")
Dim sTDir : sTDir = oFS.GetAbsolutePathName("..\data\test")
Dim oFile
For Each oFile In oFS.GetFolder(sTDir).Files
WScript.Echo "looking at", oFile.Name
' Dim & init for vars needed on *this* level
Dim sContent : sContent = goFS.GetFile(oFile.Path)
' For Skytunnels and other air-coders
WScript.Echo "content is not", sContent
' you got oFile, so use it; no need for .GetFile()
sContent = oFile.OpenAsTextStream(ForReading).ReadAll()
WScript.Echo "qed! content is", sContent
' Replace(expression, find, replacewith[, start[, count[, compare]]])
' don't use magic numbers; vbTextCompare is even pre-defined
sContent = Replace(sContent, csFind, csRepl, 1, -1, vbTextCompare)
WScript.Echo "new content", sContent
oFile.OpenAsTextStream(ForWriting).Write sContent
sContent = oFile.OpenAsTextStream(ForReading).ReadAll()
WScript.Echo "new content straight from file", sContent
WScript.Echo "------------------"
Next
output:
...
------------------
looking at 0000000000012345.20120302.pdf
content is not E:\trials\SoTrials\answers\9117277\data\test\0000000000012345.20120302.pdf
qed! content is This is the content of 0000000000012345.20120302.pdf
new content This is the content of 0000000000012345.20120302.puf
new content straight from file This is the content of 0000000000012345.20120302.puf
Important points:
Don't use a Dim-all-vars-ever-used-line at the top of your script
Avoid creation of unnecessary vars (folder, files, *contents), use
the vars you have properly (item==oFile)
.GetFile() returns a File object, not the file's content
You missed out the fso. on
oldFileContents = fso.GetFile(item.Path)
and
fso.WriteFile FileName,newFileContents
EDIT: as per discussion below, please note this answer was only meant to show where your error was occurring. It was assumed that your intent was to develop your code further once your got past this error, which if so, I’m sure you’ve already seen Ekkehard has provided some very helpful guidance on his answer.

Resources