Rename part of file - vbscript

I require a VBScript that finds the most recent file in a folder and renames it. I have been able to write the script so that it finds the most recent file. However, I cannot figure out how to correctly have the file renamed once identified. I have been able to rename the file with a basic name, confirming the script works.
The file name needs the letter "A" added in the middle.
The file will already be saved as 20160229_TITLES and it needs to become 20160229A_TITLES.
Below is a script I tried to just pull the year and add the "A". I figured if I could get the year to add to the beginning, I could then add in the month and year. The date will always be the current date. This continues to cause an error message.
Option Explicit
Dim fso, folder, file, Date, recentFile
Dim folderName, searchFileName, renameFileTo
folderName = "C:\Ticket\Test\"
Set fso = CreateObject("Scripting.FileSystemObject")
Set folder = fso.GetFolder(folderName)
Set recentFile = Nothing
For Each file In folder.Files
If (recentFile is Nothing) Then
Set recentFile = file
ElseIf FormatDateTime(file.DateLastModified) = Date Then
Set recentFile = file
End If
Next
recentFile.Name = Replace(recentFile.Name, "_", "A_")

Assuming that the filename will always consist of a date followed by an underscore and some other text you could do several things:
replace underscores with "A_" (if there is only one underscore in the name):
file.Name = Replace(file.Name, "_", "A_")
split the name at the first underscore, append "A" to the first fragment and join the fragments back together:
arr = Split(file.Name, "_", 2)
arr(0) = arr(0) & "A"
file.Name = Join(arr, "_")
do a regular expression replacement:
Set re = New RegExp
re.Pattern = "^(\d{8})_"
file.Name = re.Replace(file.Name, "$1A_")

The answer #Ansgar provided helped me correctly rename the file, however, I learned that the script only searched for any file that was newer than any other file and renamed it. The following script correctly renames the file that was modified today. Thank you for all your help #Ansgar. :)
Option Explicit
Dim fso, folder, file, todaysDate, recentFile
Dim folderName, searchFileName, renameFileTo
folderName = "C:\Ticket\Test\"
todaysDate = Date()
Set fso = CreateObject("Scripting.FileSystemObject")
Set folder = fso.GetFolder(folderName)
set recentFile = Nothing
For each file In folder.Files
If (recentFile is Nothing) Then
Set recentFile = file
ElseIf DateValue (file.DateLastModified) = todaysDate then
Set recentFile = file
Exit For
End IF
Next
recentFile.Name = Replace(recentFile.Name, "_", "A_")

Related

Read configuration information from file into VBS array [duplicate]

This question already has answers here:
Read data from ini file
(3 answers)
Closed 8 months ago.
I've written a vbs script to try delete all files over a certain age from pre-defined subfolders within a directory.
These subfolders are defined in a configuration file:
[folders]
des
dcs
I'm trying to load this data into a VBS script during runtime. The config file will be located in the same folder as the VBS script, in a subfolder called Config.
I basically want the values under [folder] stored in an array. Below is an example where I've hardcoded this using the variable codes.
Can someone please assist?
Set oFileSys = WScript.CreateObject("Scripting.FileSystemObject")
sRoot = "C:\project\Target"
today = Date
nMaxFileAge = 3
codes = Array("des", "dcs") 'hardcoded for now
For Each code in codes
textFilePath = oFileSys.BuildPath(sRoot, code)
remove_files(textFilePath)
Next
Function remove_files(path)
Set oFolder = oFileSys.GetFolder(path)
Set aFiles = oFolder.Files
Set aSubFolders = oFolder.SubFolders
For Each file in aFiles
dFileCreated = FormatDateTime(file.DateCreated, "2")
if DateDiff("d", dFileCreated, today) > nMaxFileAge Then
file.Delete(True)
End If
Next
For Each folder in aSubFolders
remove_files(folder.Path)
Next
End Function
Edit: It doesn't really matter what type of file the configuration file is. Just somewhere I can define a list of folder and read it into VBS.
The answer someone else has linked to before closing my question doesn't answer the question. See my solution below.
I managed to find some code elsewhere to help. Basically I just stored in the folder names in a text file, and read those in:
Const ForReading = 1
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objOpen = objFSO.OpenTextFile("C:\project\Target\test.txt", ForReading)
Dim code()
sRoot = "C:\project\Target"
today = Date
nMaxFileAge = 3
FileContent = objOpen.ReadAll
msgbox FileContent
codes = Split(FileContent, VbCrLF)
objOpen.Close
Set objOpen = Nothing
For Each code in codes
textFilePath = objFSO.BuildPath(sRoot, code)
msgbox textFilePath
remove_files(textFilePath)
Next
Function remove_files(path)
Set oFolder = objFSO.GetFolder(path)
Set aFiles = oFolder.Files
Set aSubFolders = oFolder.SubFolders
For Each file in aFiles
dFileCreated = FormatDateTime(file.DateCreated, "2")
if DateDiff("d", dFileCreated, today) > nMaxFileAge Then
file.Delete(True)
End If
Next
For Each folder in aSubFolders
remove_files(folder.Path)
Next
End Function

Renaming multiple files in a loop

I have a folder with 8 Excel files with the following naming convention:
date_All_Groups
date_HRFull_Status_All
date_RME_Groups_Excluded
These files are used for monthly reports, therefore the date will obviously always be different.
I will be using a macro to manipulate the data in each worksheet, however I cannot create the macro due the changing file name (the date) - the only guarantee I have is that each of these files will DEFINITELY contain a partial string match.
I have a script that finds the files in the location and will rename the file, but it only renames 1 file and its not the first file in the folder.
My issue is using the For Each loop effectively.
Here's the code I have:
Dim fso, folder, file
Dim folderName, searchFileName, renameFile1, renameFile2, renameFile3, renameFile4, renameFile5, renameFile6, renameFile7, renameFile8
'Path
folderName = "C:\test\"
'Future FileName
renameFile1 = "All Groups.csv"
renameFile2 = "Groups Excluded.csv"
renameFile3 = "No Exclusions.csv"
renameFile4 = "HR.csv"
renameFile5 = "AD Users.csv"
renameFile6 = "Encryption Status.csv"
renameFile7 = "ePO4 Not Encrypted.csv"
renameFile8 = "ePO5 Not Encrypted.csv"
' Create filesystem object and the folder object
Set fso = CreateObject("Scripting.FileSystemObject")
Set folder = fso.GetFolder(folderName)
' Loop over all files in the folder until the searchFileName is found
For Each file In folder.Files
' See If the file starts with the name we search
If InStr(file.Name, "All_Groups") then
file.Name = renameFile1
End If
If InStr(file.Name, "Groups_Excluded") Then
file.Name = renameFile2
End If
If InStr(file.Name, "No_Exclusions") Then
file.Name = renameFile3
End If
If InStr(file.Name, "HR") Then
file.Name = renameFile4
End If
If InStr(file.Name, "AD_Users") then
file.Name = renameFile5
End If
If InStr(file.Name, "Encryption_Status") then
file.Name = renameFile6
End If
If InStr(file.Name, "ePO4") then
file.Name = renameFile7
End If
If InStr(file.Name, "ePO5") then
file.Name = renameFile8
End If
Exit For
' echo the job is completed
WScript.Echo "Completed!"
Next
The original code I found was exactly as above, but with only one If statement inside the For Each loop and the Exit For was inside the If statement.
Currently when I execute the script, the code renames only one file and its always the HR file first.
If I execute the script again, it then starts with All Groups, then Groups Excluded, and so on.
And the "Echo Completed" does not do anything either.
If you just want to rename your files to "canonical" names you could do something like this, assuming that you just want the date from the beginning of the filename removed and the underscores replaced with spaces:
Set re = New RegExp
re.Pattern = "\d{4}-\d{2}-\d{2}_(.*\.csv)"
For Each f In folder.Files
For Each m In re.Execute(f.Name)
f.Name = Replace(m.Submatches(0), "_", " ")
Next
Next
If the files have the same "date" you only need Find for that, for excample (if the date is a iso date "YYYYMMDD") (Date Returns "today" date)
IsoDate=CStr(Year(Date)) & Right("0" & CStr(Month(Date)),2) & Right("0" & CStr(Day(Date)),2)
And the for each:
For Each file In folder.Files
If InStr(file.Name, IsoDate) = 1 then 'if is in the start of the string
file.Name = Mid(file.Name, Len(IsoDate)+1) 'The same name with out date
End IF
Next

VBScript to Rename File with Specific Prefix in Folder

I have successfully created a VBScript that renames a file as required when it is the only file in the folder. I cannot figure out how to have the script search past the most recent file.
Option Explicit
Dim fso, folder, file, tmFile
Dim folderName
folderName = "\\pcc\Int\PC\Inbox\"
Set fso = CreateObject("Scripting.FileSystemObject")
Set folder = fso.GetFolder(folderName)
Set tmFile = Nothing
For each file In folder.Files
If (tmFile is Nothing) Then
Set tmFile = file
Exit For
End IF
Next
If InStr(tmfile.name, "TM") Then
TmFile.Name = Replace(tmFile.Name, ".txt", "A.txt")
End if
The above script correctly renames the file.
Here are a few modifications I have tried to go through all of the files in the folder to search for the file that has the prefix TM. This will always be the only file with the TM prefix.
For Each InStr(tmFile.name, "TM") Then
tmFile.Name = Replace(tmFile.Name, ".txt", "A.txt")
Exit for
and
If tmFile.fileexists(tmFile.name, "TM") Then
tmFile.Name = Replace(tmFile.Name, ".txt", "A.txt")
End if
You are close with your instr(), it's just that you need to put that test within your already existing For loop:
Option Explicit
Dim fso, folder, file, tmFile
Dim folderName
folderName = "\\pcc\Int\PC\Inbox\"
Set fso = CreateObject("Scripting.FileSystemObject")
Set folder = fso.GetFolder(folderName)
For each file In folder.Files
If instr(file, "TM") > 0 THEN
file.name = replace(file.name, ".txt", "A.txt")
End IF
Next
I've removed the tmfile variable since it's simply not needed here.

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

If file exists then delete the file

I have a vbscript that is used to rename files. What I need to implement into the script is something that deletes the "new file" if it already exists.
For example: I have a batch of files that are named like this 11111111.dddddddd.pdf where the files get renamed to 11111111.pdf. The problem is that when I rename to the 11111111.pdf format I end of with files that are duplicated and then makes the script fail because you obviously cant have 2 files with the same name. I need it to rename the first one but then delete the others that are renamed the same.
Here is what I have so far for my IF statement but it doesnt work and I get and error that says "Type mismatch: 'FileExists". I am not sure how to get this part of the code to execute the way I would like. Any help or suggestions would be greatly appreciated.
dim infolder: set infolder = fso.GetFolder(IN_PATH)
dim file
for each file in infolder.files
dim name: name = file.name
dim parts: parts = split(name, ".")
dim acct_, date_
acct_ = parts(0)
date_ = parts(1)
' file format of a.c.pdf
if UBound(parts) = 2 then
' rebuild the name with the 0th and 2nd elements
dim newname: newname = acct_ & "." & parts(2)
' use the move() method to effect the rename
file.move fso.buildpath(OUT_PATH, newname)
if newname = FileExists(file.name) Then
newname.DeleteFile()
end if
end if
next 'file
You're close, you just need to delete the file before trying to over-write it.
dim infolder: set infolder = fso.GetFolder(IN_PATH)
dim file: for each file in infolder.Files
dim name: name = file.name
dim parts: parts = split(name, ".")
if UBound(parts) = 2 then
' file name like a.c.pdf
dim newname: newname = parts(0) & "." & parts(2)
dim newpath: newpath = fso.BuildPath(OUT_PATH, newname)
' warning:
' if we have source files C:\IN_PATH\ABC.01.PDF, C:\IN_PATH\ABC.02.PDF, ...
' only one of them will be saved as D:\OUT_PATH\ABC.PDF
if fso.FileExists(newpath) then
fso.DeleteFile newpath
end if
file.Move newpath
end if
next
fileExists() is a method of FileSystemObject, not a global scope function.
You also have an issue with the delete, DeleteFile() is also a method of FileSystemObject.
Furthermore, it seems you are moving the file and then attempting to deal with the overwrite issue, which is out of order. First you must detect the name collision, so you can choose the rename the file or delete the collision first. I am assuming for some reason you want to keep deleting the new files until you get to the last one, which seemed implied in your question.
So you could use the block:
if NOT fso.FileExists(newname) Then
file.move fso.buildpath(OUT_PATH, newname)
else
fso.DeleteFile newname
file.move fso.buildpath(OUT_PATH, newname)
end if
Also be careful that your string comparison with the = sign is case sensitive. Use strCmp with vbText compare option for case insensitive string comparison.
IF both POS_History_bim_data_*.zip and POS_History_bim_data_*.zip.trg exists in Y:\ExternalData\RSIDest\ Folder then Delete File Y:\ExternalData\RSIDest\Target_slpos_unzip_done.dat

Resources