VBS script to rename files using the pathname - vbscript

i am new to VBS scripting and I have done few stuff with Excel VBA before. Now I have a script which renames single files with the pathname of the files (truncated to 4 letter each))see below. It is some script which I modified a bit to fit my purpose. However, I would like to automatize the file rename process and rename all files in a folder and its subfolders in the same way the scipt works for single files. Can anybody help me with this question?
Set Shell = WScript.CreateObject("WScript.Shell")
Set Parameter = WScript.Arguments
For i = 0 To Parameter.Count - 1
Set fso = CreateObject("Scripting.FileSystemObject")
findFolder = fso.GetParentFolderName(Parameter(i))
PathName = fso.GetAbsolutePathName(Parameter(i))
FileExt = fso.GetExtensionName(Parameter(i))
Search = ":"
findFolder2= Right(PathName, Len(PathName) - InStrRev(PathName, Search))
arr = Split(findFolder2, "\")
For j=0 To UBound(arr)-1
arr(j) = ucase(Left(arr(j), 4))
Next
joined = Join(arr, "%")
prefix = right(joined, len(joined)-1)
fso.MoveFile Parameter(i), findFolder + "\" + prefix
next
Hoping that I can get some useful ideas.
Herbie

Walking a tree requires recursion, a function calling itself for each level.
On Error Resume Next
Set fso = CreateObject("Scripting.FileSystemObject")
Dirname = InputBox("Enter Dir name")
ProcessFolder DirName
Sub ProcessFolder(FolderPath)
On Error Resume Next
Set fldr = fso.GetFolder(FolderPath)
Set Fls = fldr.files
For Each thing in Fls
msgbox Thing.Name & " " & Thing.DateLastModified
Next
Set fldrs = fldr.subfolders
For Each thing in fldrs
ProcessFolder thing.path
Next
End Sub
From Help on how to run another file.
Set Shell = WScript.CreateObject("WScript.Shell")
shell.Run(strCommand, [intWindowStyle], [bWaitOnReturn])
So outside the loop,
Set Shell = WScript.CreateObject("WScript.Shell")
And in the loop
shell.Run("wscript Yourscript.vbs thing.name, 1, True)
Also the VBS help file has recently been taken down at MS web site. It is available on my skydrive at https://1drv.ms/f/s!AvqkaKIXzvDieQFjUcKneSZhDjw It's called script56.chm.

Related

VB script file system object "MoveFile" method giving permission denied error

I have written a small script to rename a file based on an ID number within. I have never worked with vbs before, so I am still quite unfamiliar with it. I have worked out most of the issues and everything is working correctly up until the MoveFile command at the end. Just for testing purposes, I have the files saved to C:\temp and am trying to moveFile back to C:. Is this not allowed or something?
Here is my code:
Dim objFSO,foldername, folder, objFile, tsfiles, f1, textfile, line, filename, destinationfile
foldername = "C:\Temp"
Const ForReading = 1
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set folder = objFSO.GetFolder(foldername)
Set tsfiles = folder.Files
For each f1 in tsfiles
filename = f1.name
textfile = foldername + "\" + filename
If Instr(f1.name, ".TS") <> 0 Then
Set objFile = objFSO.OpenTextFile((textfile), ForReading)
Do Until objFile.AtEndOfStream
objFile.ReadLine
line = objFile.ReadLine
If Instr(line, "RECORDER ID:") <> 0 Then
Dim RID
RID = trim(Mid(line, 15, 15))
destinationfile = foldername + "\" + RID + ".txt"
MsgBox(destinationfile)
objFSO.MoveFile textfile, destinationfile
objFile.close
End If
Loop
End if
Next
You are opening then text file and the you try to move it while it's still open. You'll have to close it prior to moving it.
Also, this ain't specific to vbscript but usually, moving files in the system drive (in your case the C:) requires administrator privileges. I think those rules has been enforced after Windows XP so you may also need to run the script as administrator.
To run as admin you need to right click on it and specifically run as admin.
In your code you are trying to move while it's open. If you close it, thats fie but then it continues to go through the loop and when it tries to access the open file it fails. So you need to close it and break out of the loop. Exit Do will break out of the loop so it doesn't go back and try and evaluate objFile.AtEndOfStream against a closed object.
Dim objFSO,foldername, folder, objFile, tsfiles, f1, textfile, line, filename, destinationfile
foldername = "C:\Temp"
Const ForReading = 1
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set folder = objFSO.GetFolder(foldername)
Set tsfiles = folder.Files
For each f1 in tsfiles
filename = f1.name
textfile = foldername + "\" + filename
If Instr(f1.name, ".TS") <> 0 Then
Set objFile = objFSO.OpenTextFile((textfile), ForReading)
Do Until objFile.AtEndOfStream
objFile.ReadLine
line = objFile.ReadLine
If Instr(line, "RECORDER ID:") <> 0 Then
Dim RID
RID = trim(Mid(line, 15, 15))
destinationfile = foldername + "\" + RID + ".txt"
MsgBox(destinationfile)
objFile.close
objFSO.MoveFile textfile, destinationfile
Exit Do
End If
Loop
End if
Next

How to run windows executable and delete files from sub folders

I need a quick script do two parts.
Run a windows executable
Delete files within a folder and subfolders (*.jpg, *.img).
The first part of the below script works (running the executable) but I am getting stuck on part 2. I get
Cannot use parentheses when calling a sub
The error is on the line with the RecursiveDelete call. I actually cut and pasted that code from another SO question. I have googled the error but still don't understand.
Can anybody know how to get this script working?
Set WshShell = CreateObject("WScript.Shell")
WshShell.Run chr(34) & "C:\Users\acer\Desktop\CT\process.exe" & Chr(34), 0
Set WshShell = Nothing
Dim PicArray(2)
Dim p
PicArray(1) = "*.jpg"
PicArray(2) = "*.img"
For p = 1 To 2
RecursiveDelete ("D:\pictures", PicArray(p))
Next p
Private Sub RecursiveDelete(ByVal Path As String, ByVal Filter As String)
Dim s
For Each s In System.IO.Directory.GetDirectories(Path)
try
RecursiveDelete(s, Filter)
catch dirEx as exception
debug.writeline("Cannot Access " & s & " : " & dirEx.message
end try
Next
For Each s In System.IO.Directory.GetFiles(Path, Filter)
try
System.IO.File.Delete(s)
catch ex as exception
debug.writeline("Cannot delete " & s & " : " & ex.message)
end try
Next
End Sub
Update: Revised answer from Hackoo that works great.
Option Explicit
Dim fso,RootFolder, wshShell
set fso = CreateObject("Scripting.FileSystemObject")
RootFolder = "D:\pictures"
Set RootFolder = fso.GetFolder(RootFolder)
Call RecursiveDelete(RootFolder)
Set WshShell = CreateObject("WScript.Shell")
WshShell.Run chr(34) & "C:\process.exe" & Chr(34), 0
Set WshShell = Nothing
'*****************************************************************************
Function RecursiveDelete(Folder)
Dim File,MyFile,Ext,i,SubFolder
Set Folder = fso.GetFolder(Folder)
For each File in Folder.Files
Set MyFile = fso.GetFile(File)
Ext = Array("iMG","JPG")
For i = LBound(Ext) To UBound(Ext)
If LCase(fso.GetExtensionName(File.name)) = LCase(Ext(i)) Then
MyFile.Delete()
Exit For
end if
Next
Next
For each SubFolder in Folder.SubFolders
Call RecursiveDelete(SubFolder)
Next
End Function
'*****************************************************************************
Try like this way :
Option Explicit
Dim fso,RootFolder
set fso = CreateObject("Scripting.FileSystemObject")
RootFolder = "D:\pictures"
Set RootFolder = fso.GetFolder(RootFolder)
Call RecursiveDelete(RootFolder)
Msgbox "Pictures Cleaned !",vbInformation,"Pictures Cleaned !"
'*****************************************************************************
Function RecursiveDelete(Folder)
Dim File,MyFile,Ext,i,SubFolder
Set Folder = fso.GetFolder(Folder)
For each File in Folder.Files
Set MyFile = fso.GetFile(File)
Ext = Array("jpg","img")
For i = LBound(Ext) To UBound(Ext)
If LCase(fso.GetExtensionName(File.name)) = LCase(Ext(i)) Then
MyFile.Delete()
Exit For
end if
Next
Next
For each SubFolder in Folder.SubFolders
Call RecursiveDelete(SubFolder)
Next
End Function
'*****************************************************************************
Instead of passing the array item into RecursiveDelete, obtain the contents of the array item into a variable within the loop, and pass that variable instead.
Code would be similar to this- did not have a chance to test syntax.
For p = 1 To 2
Dim PicItem
PicItem = PicArray(p)
RecursiveDelete ("D:\pictures", PicItem )
Next p

How to Copy a file that was read from a list

Hello guys I have an issue or issues with my code above
I'm trying to get "sExtension" to be search in a different folder other that the one I'm using to save my script since this script will be use as a Startup Script on many computers
(It works only if I run the script in the same folder "sExtension", "ExtAssign.txt" and sComputername are otherwise it wont find the path)
This is what it should do
Read a file called "ExtAssign.txt" (There is a full list of computer names in that file) and if it find the computer name on that file then it should copy a file with the with the extension number assigned to that computer name from a file server to "C:\" Drive
For this example I'm trying to do this locally, If I can make it then I'll try it from my File Server
Set objFSO = CreateObject("Scripting.FileSystemObject")
set oFso = CreateObject("Scripting.FileSystemObject")
Set objFS = CreateObject("Scripting.FileSystemObject")
Set fso = CreateObject("Scripting.FileSystemObject")
set oShell = WScript.CreateObject("WScript.Shell")
set oShellEnv = oShell.Environment("Process")
Set folder = Fso.GetFolder("C:\Users\XXXXX\Desktop\Test\Extensions\")
Set wshshell = CreateObject("WScript.Shell")
Set objNetwork = CreateObject("WScript.Network")
Set ObjEnv = WshShell.Environment("Process")
Set objFso = WScript.CreateObject("Scripting.FileSystemObject")
Scomputername = ObjEnv("COMPUTERNAME")
Set objFSO = CreateObject("Scripting.FileSystemObject")
set objWShell = wScript.createObject("WScript.Shell")
Dim strFile
'File to scan
strFile = "C:\Users\XXXXX\Desktop\Test\Extensions\Extassign\ExtAssign.txt"
Dim strPattern
'Look for computer name in file
strPattern = scomputername
Set objFso = WScript.CreateObject("Scripting.FileSystemObject")
Set objFile = objFS.OpenTextFile(strFile)
Do Until objFile.AtEndOfStream
Dim strLine
'Read each line and store it in strLine
strLine = objFile.ReadLine
'If the line matches the computer name, save the line to ExtArray
If InStr(strLine,strPattern)>0 Then
Dim ExtArray
'Split the line and separate the extension
ExtArray = Split(strLine,"|", -1, 1)
Dim sExtension
'Save the extension to sExtension
sExtension=ExtArray(1)
End If
Loop
'If the sExtension is empty, computer was not found, send message and terminate script.
If sExtension="" Then
WScript.Echo "ERROR: Computer "& scomputername &" not found in Extension Assignment List, so no extension has been set. Avaya will not be launched. Please contact your IT department for assistance."
Else
'If the sExtension contains a number, Copy that file to C:\ and rename it to Config.xml
fso.CopyFile "C:\Users\XXXXX\Desktop\Test\Extensions\ "& sExtension &"", "C:\Config.xml", True
End If
at the end it if it finds the file sExtension it will rename it to Config.xml but it wont do it unless I run the script in the same folder sExtension and sComputername.
I get File not found error
Thank you in advance and Happy new year!
The culprit is most likely this line:
fso.CopyFile "C:\Users\XXXXX\Desktop\Test\Extensions\ "& sExtension &"", "C:\Config.xml", True
There is a trailing space after the last backslash in the path, so you're creating a path
C:\Users\XXXXX\Desktop\Test\Extensions\ 12345
^
when you actually want a path
C:\Users\XXXXX\Desktop\Test\Extensions\12345
On a more general note: why are you creating 7(!) FileSystemObject instances (replacing one of them three times on top of that)? And 3(!) WScript.Shell instances? You don't even use most of them, not to mention that you don't need the Shell object in the first place. You only use it for determining the computer name, which could be done just fine using the WScript.Network object (that you don't use at all).
Also, please don't ever use comments like this:
'Read each line and store it in strLine
strLine = objFile.ReadLine
It's quite obvious that you read each line and assign it to the variable strLine. Comments shouldn't rephrase what you're doing (the code already does that, at least when you're using speaking variable and function names), but why you're doing it, i.e. what the purpose of a particular code section is.
Your code could be reduced to something as simple as this:
Set fso = CreateObject("Scripting.FileSystemObject")
Set net = CreateObject("WScript.Network")
computername = net.ComputerName
foldername = "C:\Users\XXXXX\Desktop\Test\Extensions"
filename = fso.BuildPath(foldername, "Extassign\ExtAssign.txt")
Set f = fso.OpenTextFile(filename)
Do Until f.AtEndOfStream
line = f.ReadLine
If InStr(line, computername) > 0 Then
arr = Split(line, "|", -1, 1)
If UBound(arr) >= 1 Then extension = arr(1)
End If
Loop
f.Close
If IsEmpty(extension) Then
WScript.Echo "ERROR: Computer "& computername &" not found in ..."
Else
fso.CopyFile fso.BuildPath(foldername, extension), "C:\Config.xml", True
End If

Script to move first 3 characters of filename to the end

I have a directory full of files that I need to rename. For each file, I need to take the first three characters of the filename and move them to the end of the filename before the extension.
So 003999999.wav would become 999999003.wav.
The scripting language doesn't really matter. It just needs to work in Windows. This seems like it'd be an easy script using vbscript and I'm currently doing some reading, but figured I'd see if someone already has something like this that would work.
Edit - So I think I've found how to do this, except the part on getting the filename characters. Here's what I have.
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFolder = objFSO.GetFolder("C:\Directory")
For Each strFile in objFolder.Files
arrNames = Split(strFile.Name, ".")
If arrNames(1) = "mp3" Then
Set objstart = objFSO.Range(0,3)
Set objend = objFSO.Range(4,17)
strNewName = "C:\Directory\" & objend.Text & objstart.Text & ".mp3"
objFSO.MoveFile strFile.Path, strNewName
End If
Next
Try this script. I used simple string functions to manipulate each filename.
'Rename Files
'============
Dim objFSO, objFolder, strFile, intLength, firstThree, restofName, strNewName
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFolder = objFSO.GetFolder("C:\Directory")
For Each strFile in objFolder.Files
'Get files by extension
If objFSO.GetExtensionName(strFile.Name) = "mp3" Then
'Use instr to get the location of the "." and subtract 1 for the "."
intLength = InStr(1,strFile.Name,".",1)-1
'Use the Left function to get the first three characters of the filename
firstThree = Left(strFile.Name,3)
'Use the Mid function to get the rest of the filename subtract 3 for the file extension
restofName = Mid(strFile.Name,4,intLength -3)
strNewName = "C:\Directory\" & restofName & firstThree & ".mp3"
objFSO.MoveFile strFile.Path, strNewName
End If
Next
WScript.Echo "Done!"
Instead of the fictional .Range method, use a regular expression:
>> s1 = "003999999.wav"
>> Set r = New RegExp
>> r.Pattern = "(\d{3})(\d+)(\.wav)"
>> s2 = r.Replace(s1, "$2$1$3")
>> WScript.Echo s2
>>
999999003.wav
to cut three digits (\d{3}), the other digits (d+), and the (escaped) dot followed by the extension (wav) from the input string and re-arange the 3 parts in the .Replace.
Simplified version of JP's solution:
Set fso = CreateObject("Scripting.FileSystemObject")
For Each f In fso.GetFolder("C:\Directory").Files
extension = fso.GetExtensionName(f.Name)
If LCase(extension) = "mp3" Then
basename = fso.GetBaseName(f.Name)
f.Name = Mid(basename, 4) & Left(basename, 3) & "." & extension
End If
Next
In batch you'd do it like this:
#echo off
setlocal EnableDelayedExpansion
for %%f in (C:\Directory\*.mp3) do (
set basename=%%~nf
ren "%%~ff" "!basename:~3!!basename:~0,3!%%~xf"
)
endlocal

vbScript to execute all files in a dir

I'm trying to write a vbScript that will execute all files in a given directory (will be mostly batch files).
I've tried to modify a script that deletes all files but I'm not able to get it to work.
Here is what I have:
Option Explicit
'===========================================================================
' Scheduled Task - Visual Basic ActiveX Script
'===========================================================================
Call ExecuteDirectory("c:\users\public\documents\schedule\daily")
Function ExecuteDirectory(strPath2Folder)
Dim fso, f, fc, f1, strFiles, intFiles
Dim WshShell
Set WshShell = CreateObject("WScript.Shell")
strFiles = ""
Set fso = CreateObject("Scripting.FileSystemObject")
If (fso.FolderExists(strPath2Folder)) Then
Set f = fso.GetFolder(strPath2Folder)
Set fc = f.Files
'-- Execute each file in Folder
For Each f1 in fc
strFiles = strFiles & f1.Name & vbCrLf
msgbox strPath2Folder & "\" & strFiles
WshShell.Run Chr(34) & strFiles & Chr(34), 1, true
Next
Set f1 = Nothing
Set fc = Nothing
Set f = Nothing
End If
Set fso = Nothing
End Function
The msgbox line displays the full path and file name that I want to execute, but the run line generates file not found error.
The variable strFiles continually builds up a list of files with line breaks in between. For example, if your folder contains the files "test1.bat" and "test2.bat", you will end up with this:
Iteration 1:
strFiles =
test1.bat
Iteration 1:
strFiles =
test1.bat
test2.bat
I don't think this is what you want to do. If you want to just run each script in order, you should just pass the single script name.
Try changing the inner loop to this:
For Each f1 in fc
Dim fileToRun
fileToRun = strPath2Folder & "\" & f1.Name
WshShell.Run Chr(34) & fileToRun & Chr(34), 1, true
Next
This is a very sloppy approach. If you are needing to execute an entire directory of batch files at one time, then you are not using them correctly. You should only need one batch file or one script an any time. I would begin looking at your whole system for a better approach to whatever it is that you are trying to accomplish.

Resources