VBS Copy Files from a text file - arrays

Hiya Guys I have a text file with locations of files I'm looking for a way to read the text file and then use those locations as a source location and copy the files to a seperate destination.
I've been playing around and have seen about dynamic arrays but cant seem to understand how to put the contents of the array into variables to read as source location.
example of what I have done so far
Dim TxtFile
dim strDestinationFolder
strDestinationFolder = "\\SERVER\DESTLOGS"
TxtFile = "c:\windows\temp\SOFTWARELOG.txt"
Dim fso: Set fso = CreateObject("Scripting.FileSystemObject")
Dim f: Set f = fso.OpenTextFile(TxtFile)
Do Until f.AtEndOfStream
WScript.Echo "PSTLocation: " & f.ReadLine ; I can read each line here in the txt file
fso.CopyFile strDestinationFolder, f.REadline
Loop
I've also tried playing with, but not sure where to start though it looks the most reliable?
Const ForReading = 1
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objTextFile = objFSO.OpenTextFile _
(TxtFile, ForReading)
Do Until objTextFile.AtEndOfStream
strNextLine = objTextFile.Readline
arrServiceList = Split(strNextLine , ",")
WScript.Echo "Server: " & arrServiceList(0)
WScript.Echo "Service: " & objTextFile
For k = 1 to UBound(arrServiceList)
WScript.Echo vbTab & "Service: " & arrServiceList(i)
Next
Loop
Any Guidance please as to what is the best way I should go about this with vbs.
Thanks

WScript.Echo "PSTLocation: " & f.ReadLine
fso.CopyFile strDestinationFolder, f.REadline
Your code echoes one line read from the file, and then tries to copy the destination folder to the next line read from the file.
If you want to do more than one thing with a line read from a file you need to assign the read line to a variable and then use that variable. Also, you need to switch the arguments of the CopyFile method. Source comes first, then destination. Plus, if you want the destination to be a folder, it needs a trailing backslash (otherwise you'd try to overwrite a folder with a file, which raises an error).
Do Until f.AtEndOfStream
line = Trim(f.ReadLine)
WScript.Echo "PSTLocation: " & line
If fso.FileExists(line) Then fso.CopyFile line, strDestinationFolder & "\"
Loop
The Trim() accounts for spurious leading/trailing spaces in the read line, and it's always a good idea to check if a file actually exists before you try to do anything with it.
Edit: For detecting an existing destination file and appending a running number to the file name try something like this:
basename = fso.GetBaseName(line)
extension = fso.GetExtensionName(line)
destinationFile = fso.BuildPath(strDestinationFolder, basename & "." & extension)
i = 1
Do While fso.FileExists(destinationFile)
filename = basename & i & "." & extension
destinationFile = fso.BuildPath(strDestinationFolder, filename)
i = i + 1
Loop
fso.CopyFile line, destinationFile

Related

VBS to Rename File via Send To Menu

Every day I have to rename files to replace spaces with dashes before I can send them to our machines (a few of our machines don't read spaces in file names but our file naming conventions have spaces, a conflict of interest I know).
Sometimes it's one file others it's a half dozen so my approach is to use the Windows Send To menu to send selected files to the script.
I've gotten as far as renaming the strings but the actual move function says path not found when I get to the fso.movefile function.
Here's what I have so far.
Set objArgs = WScript.Arguments
Dim Fso
Set Fso = WScript.CreateObject("Scripting.FileSystemObject")
'Cycle through files
For I = 0 to objArgs.Count - 1
' Assign array entry to variable
t = objArgs(I)
' Parse variable to replace spaces with dashes
s = Replace(t, " ", "-")
' Let me know how I did
WScript.Echo t & vbcrlf & s
'Move 'em
fso.movefile t, s
Next
Any help will be greatly appreciated.
So my problem was the folder I was in had spaces too. So my code was trying to rename to a folder that didn't exist.
Once I parsed the file name out of the path and re-grouped the modified file name it worked great. Code below.
Dim t ' original file and path
Dim s ' file name only with spaces
Dim u ' new file name without spaces
Dim v ' path only
Dim obj
Set objArgs = WScript.Arguments
set obj = WScript.CreateObject("Scripting.FileSystemObject")
'Cycle through files
For I = 0 to objArgs.Count - 1
' Assign array entry to variable
t = objArgs(I)
' Parse file name from path
s = Right(t, Len(t) - InStrRev(t, "\"))
' Remove file name from path
v = left(t, InStrRev(t, "\"))
' Parse variable to replace spaces with dashes
u = Replace(s, " ", "-")
' ' Let me know how I did
' WScript.Echo "Was(t): " & t & vbcrlf & "Is(s): " & s & vbcrlf & "Path: " & v
'Move 'em
obj.movefile t, v & u
Next

moving oldest files

I was looking for a way to move the 5 oldest modified files in a folder to a different folder.
I came across some helpful pieces of code and I revised it to this:
Dim files
Dim startFolder
Dim destinationFolder
Dim oldestFile
Dim file
Dim FSO
startFolder = "C:\logs\current"
destinationFolder = "C:\logs\backup"
Set FSO = CreateObject("Scripting.FileSystemObject")
Set files = FSO.GetFolder(StartFolder).files
Set oldFiles = CreateObject("System.Collections.ArrayList")
If files.Count <= 5 Then
WScript.Quit
End If
For i = 0 To 4
Set files = FSO.GetFolder(StartFolder).files
Set oldFiles = Nothing
For Each file In files
If Not IsObject(oldestFile) Then
Set oldestFile = file
Else
If file.DateLastModified < oldestFile.DateLastModified Then
Set oldestFile = file
End If
End If
Next
WScript.Echo "OLDEST: " & oldestFile.Name
oldestFile.Move destinationFolder & "\" & oldestFile.Name
Next
Basically what it supposed to do is:
loop 5 times,
each time loop through the files and assign the oldest to oldestFile,
move the file to a different location.
However, it doesn't work, it's echoing the first file's name 5 times and move just this one.
I thought I should set the objects to Nothing to start fresh but to no avail.
You need to reset the variable oldestFile at the beginning (or end) of your loop, not the variable oldFiles.
For i = 0 To 4
Set files = FSO.GetFolder(StartFolder).files
Set oldestFile = Nothing
For Each file In files
...
Next
WScript.Echo "OLDEST: " & oldestFile.Name
oldestFile.Move destinationFolder & "\" & oldestFile.Name
Next
Otherwise the value of oldestFile will never change, because even after being moved the referenced file ramains the oldest file compared to the files in the source folder.

Remove file extension from returned list of files

I have the below code that obtains a list of txt files from a folder, I would like to remove the .txt from the returned file name, how may I achieve this?
Set objFSO = CreateObject("Scripting.FileSystemObject")
objStartFolder = "Notes"
Set objFolder = objFSO.GetFolder(objStartFolder)
Set colFiles = objFolder.Files
For Each objFile in colFiles
If UCase(objFSO.GetExtensionName(objFile.name)) = "TXT" Then
document.write objFile.name & "<br>"
End If
Next
This will work:
...
For Each objFile in colFiles
If UCase(objFSO.GetExtensionName(objFile.name)) = "TXT" Then
document.write Left(objFile.name, Len(objFile.name)-4) & "<br>"
End If
Next
According to the docs, Left()
Returns a specified number of characters from the left side of a string.
You just need to know how many characters to return. Since you already know that the filename ends in .txt, you can return all but the last 4 characters. Len(objFile.name) will give you the full length, and you can subtract from there.
Or if you prefer to use a function that processes a string, I coded this for my own site once. This function returns the filename without extension, provided there is a "." anywhere in the filename, of course. If not, it simply returns the input filename.
Function RemoveFileExtension(inputFileName)
IF NOT inStr(inputFileName, ".") > 0 THEN
' Period not found
strReturnvalue = inputFileName
ELSE
' Period found. Locate last
intPositionRight = 1
DO WHILE NOT inStr(right(inputFileName, intPositionRight), ".") > 0
intPositionRight = intPositionRight + 1
LOOP
strReturnvalue = left(inputFileName, len(inputFileName) - intPositionRight)
END IF
RemoveFileExtension = strReturnvalue
End Function
Then you can simply use the function, e.g. like this:
For Each objFile in colFiles
response.write RemoveFileExtension(objFile.name) & "<br>"
Next
Happy coding. :)

Batch file running two vbs scripts for backing up

I have a system that's running an old FoxPro program which generates 8 character long DBF files. We make a back up of the program folder each day, but at 5pm the program has generated so many of these garbage dbf's that it's a nuisance. I would just set a del *.dbf in the back up script but there are a few dbf with letters in their name that are needed to run the program.
Files are located in F:\Clean This\
Any numerically titled .dbf files need to be deleted
Any alphabetically titled .dbf file should be left alone
Set objFSO = CreateObject("Scripting.FileSystemObject")
objStartFolder = "F:\Clean This\"
Set objFolder = objFSO.GetFolder(objStartFolder)
Set colFiles = objFolder.Files
collide = "ABCEDFGHIJKLMNOPQRSTUVWXYZ"
For Each objFile in colFiles
If UCase(objFSO.GetExtensionName(objFile.name)) = "DBF" Then
num = 1
For num = 1 to 26 'find files with names start with # 0-9
If Left(objFile.Name,1) = Left(collide,num) Then
Wscript.Echo "Save " & objFile.Name
Else If int(Left(objFile.Name,1)) > 0 Then
Wscript.Echo "Delete!"
End IF
End If
Next
End If
Next
As you can tell the If statements can be done better, I'm unsure how to better work it out. The two Wscript.Echo commands are just placeholders because if anything else I can't get find a suitable delete function that would work in a dos environment (I've already tried kill, no).
Suggestions and improvements would be much appreciated!
Use IsNumeric() to check for file names consisting of digits only:
>> For Each sN In Split("abc 123 1O1 101")
>> If IsNumeric(sN) Then
>> WScript.Echo "delete", sN
>> Else
>> WScript.Echo "keep", sN
>> End If
>> Next
>>
keep abc
delete 123
keep 1O1
delete 101
Your check fails, because you use Left() where you should use Mid():
>> collide = "ABCEDFGHIJKLMNOPQRSTUVWXYZ"
>> num = 5
>> WScript.Echo Left(collide,num)
>> WScript.Echo Mid(collide,num,1)
>>
ABCED
D
and even then Left(objFile.Name,1) will look at only the first character of the file name.
Update (wrt comments):
Apply IsNumeric() to the base name:
Dim oFile
For Each oFile In goFS.GetFolder("..\testdata\17817161").Files
WScript.Stdout.Write oFile.Name
If "dbf" = LCase(goFS.GetExtensionName(oFile.Name)) Then
If IsNumeric(goFS.GetBaseName(oFile.Name)) Then
WScript.Stdout.WriteLine " delete"
Else
WScript.Stdout.WriteLine " keep"
End If
Else
WScript.Stdout.WriteLine " ignore"
End If
Next
output:
123.dbf delete
123.txt ignore
abc.dbf keep
I did finally got it working, and here's what the end result was. It works wonderfully and the higher ups and others were rather impress that it worked better than the built in utility of the program we're backing up. Score!
Set objFSO = CreateObject("Scripting.FileSystemObject")
objStartFolder = "..\System Folder"
Set objFolder = objFSO.GetFolder(objStartFolder)
Set DirFiles = objFolder.Files
Dim oFile
For Each objFile in DirFiles
If "dbf" = LCase(objFSO.GetExtensionName(objFile.Name)) Then
If IsNumeric(objFSO.GetBaseName(objFile.Name)) Then
objFSO.DeleteFile(objFile)
End If
End If
Next

What is the EASIEST way to merge several delimited text files / ignore all 1st row (headers) below the first master file?

And by easiest, I don't mean shelling out $80 for Bulk File Merger. Is there other freeware or some simple code to merge SEVERAL files at once?
Thanks!
In DOS you can use the more command:
http://www.computerhope.com/morehlp.htm
the more command is probably limited to files of 64k or less in size.
I believe the syntax would be
more +1 (filespec) >> outfile
In unix you can use cat and sed to accomplish the same thing
http://www.grymoire.com/Unix/Sed.html
alternatively, in windows you can write a shell script - this one from msdn does most of it...
Const ForReading = 1
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objOutputFile = objFSO.CreateTextFile("output.txt")
strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set FileList = objWMIService.ExecQuery _
("ASSOCIATORS OF {Win32_Directory.Name='z:\Scripts\Test'} Where " _
& "ResultClass = CIM_DataFile")
For Each objFile In FileList
Set objTextFile = objFSO.OpenTextFile(objFile.Name, ForReading)
strText = objTextFile.ReadAll
objTextFile.Close
objOutputFile.WriteLine strText
Next
objOutputFile.Close
The one thing left for you to do would be to remove the first line of each file by modifying the strText variable, which holds the text of each file as they are processed.

Resources