GP SoftwareTwitter
Opus FAQsManualCommandsObjects

Recursive copy/rename function

I have tried to achieve what I am about to ask, but so far have found it difficult, mainly because as far as I am concerned, the whole scripting side of things (even with the script builder in Dopus) is a Dark Art involving the sacrifice of large numbers of chickens and children!

As such, I am not even sure if Dopus can do what I am being asked (by a client), but confident in the program (I used to use it on the Amiga platform many years ago and bought it for the PC once GPSoft started developing it), I said it could be done!

This particular client wishes to be able to select a file, and duplicate it a defined number of times (ie: a prompt for the # of copies would be good).

He then wants every copy to have a numerical identifier appended to the filename. All of this should occur seamlessly, and without user intervention after the # of clones has been determined. He is currently claiming that if DOpus can do this, he'll buy a license - I've already told him to buy a license anyway, but some people won't be told :wink:

If you have the time, I'd appreciate any insights into how to achieve this, or even if Dopus can handle this itself without external coding. I know how to duplicate a file, and how to rename (even automatically), it's tying these together with the requester for number of interations that is stumping me.

Regards

Adam

Here is my solution, using Opus to get the details (filenames and number of copies to make) and VBScript to create the copies (since there isn't a good way to loop in Opus directly).

I've attached a zip file containing the button and the VBScript, but they're also listed below so that people don't have to download the zip just to see how it works.

First, the Opus button:

@set NumDupes = {dlgstring|Number of duplicates to create:|10} "C:\Users\Leo\Desktop\DupeFile.vbs" {filepath$} {$NumDupes}

Of course, change the C:\Users\Leo\Desktop part to match where you've put DupeFile.vbs.

I created a NumDupes variable so that the button will work better when multiple files are selected. If it is used like that then it will ask once for the number of duplicates to make and then make that many copies of each selected file.

You can change the "10" in the button if you want a different default number of copies.

Here's the same button in XML format so you can paste it directly into a toolbar:

<?xml version="1.0"?> <button display="both" label_pos="right"> <label>Create Multiple Duplicates</label> <icon1>#duplicate</icon1> <function type="normal"> <instruction>@set NumDupes = {dlgstring|Number of duplicates to create:|10}</instruction> <instruction>&quot;C:\Users\Leo\Desktop\DupeFile.vbs&quot; {filepath$} {$NumDupes}</instruction> </function> </button>

Finally, here is the DupeFile.vbs which does most of the work:

[code]option explicit

Dim fs
Set fs = CreateObject("Scripting.FileSystemObject")

Dim args
set args = WScript.Arguments

if args.Count <> 2 then
MsgBox "DupeFile.vbs: Wrong number of arguments." & vbCRLF & vbCRLF & "Give the full path to the file to duplicate as the first arg." & vbCRLF & vbCRLF & "Give the number of copies to make as the second arg."
WScript.Quit 1
end if

Dim InputFilePath
InputFilePath = args.Item(0)

Dim NumberOfCopies
NumberOfCopies = args.Item(1)

Dim PadTo
PadTo = Len(CStr(NumberOfCopies))

If NumberOfCopies <= 0 Or PadTo = 0 Then
MsgBox "DupeFile.vbs: Number of copies must be a number greater than zero."
WScript.Quit 1
End If

If fs.FolderExists(InputFilePath) Then
MsgBox "DupeFile.vbs: """ & InputFilePath & """ is a folder. Only files are supported."
WScript.Quit 1
End If

If Not fs.FileExists(InputFilePath) Then
MsgBox "DupeFile.vbs: """ & InputFilePath & """ cannot be found."
WScript.Quit 1
End If

Dim LastDot
Dim LastSlash1
Dim LastSlash2

LastDot = InStrRev(InputFilePath, ".")
LastSlash1 = InStrRev(InputFilePath, "")
LastSlash2 = InStrRev(InputFilePath, "/")

Dim LeftPart
Dim RightPart

If LastDot > LastSlash1 And LastDot > LastSlash2 Then
LeftPart = Left(InputFilePath, LastDot - 1)
RightPart = Right(InputFilePath, Len(InputFilePath) - (LastDot - 1))
Else
LeftPart = InputFilePath
RightPart = ""
End If

Dim CurrentNum
Dim OutputFilePath
Dim StrNum

For CurrentNum = 1 To NumberOfCopies
StrNum = CStr(CurrentNum)

If Len(StrNum) < PadTo Then
	StrNum = String(PadTo - Len(StrNum), "0") & strNum
End If

OutputFilePath = LeftPart & "_" & StrNum & RightPart

fs.CopyFile InputFilePath, OutputFilePath, False

Next[/code]
Create Multiple Duplicates.zip (1.14 KB)

You are a true gent, Leo!

Thank you so much for your response - I shall pass it on to my client and let you know their response.

He has since purchased Opus anyway, so he should be able to implement your solution immediately :slight_smile:

Thanks again

Regards

Adam

Very nice Nudel !
I had thought on this some,
but I became confused as I wasn't certain what NLight really meant by 'recursive'.

@NLight

[quote]I have tried to achieve what I am about to ask, but so far have found it difficult, mainly because as far as I am concerned, the whole scripting side of things (even with the script builder in Dopus) is a Dark Art involving the sacrifice of large numbers of chickens and children!
[/quote]
Very funny, thanks much !
Good legal thinking !

@Nudel
Well, now that you have an excellent solution to this problem,
I have one suggestion, or rather a request.
Can a DOpus SetAttr Created command be added at the end?
In other words, can the created time stamp of the original file be preserved ?

I still don't understand VBS well yet, so I thought I'd ask.
It's a wonderful script for tinkering with photos !

Regards,
David

It's easy to copy the attributes (read-only, hidden, etc.) of the source file, using the VBScript File object.

Unfortunately VBScript doesn't provide any good way to copy the modified or created timestamps. You can read them, using the File object, but for some reason they are read-only properties. :frowning:

If anyone wants to modify the script so that it copies the attributes then you just need to insert four lines of code. Here's the new version. I've highlighted the new lines with comments:

[code]option explicit

Dim fs
Set fs = CreateObject("Scripting.FileSystemObject")

Dim args
set args = WScript.Arguments

if args.Count <> 2 then
MsgBox "DupeFile.vbs: Wrong number of arguments." & vbCRLF & vbCRLF & "Give the full path to the file to duplicate as the first arg." & vbCRLF & vbCRLF & "Give the number of copies to make as the second arg."
WScript.Quit 1
end if

Dim InputFilePath
InputFilePath = args.Item(0)

Dim NumberOfCopies
NumberOfCopies = args.Item(1)

Dim PadTo
PadTo = Len(CStr(NumberOfCopies))

If NumberOfCopies <= 0 Or PadTo = 0 Then
MsgBox "DupeFile.vbs: Number of copies must be a number greater than zero."
WScript.Quit 1
End If

If fs.FolderExists(InputFilePath) Then
MsgBox "DupeFile.vbs: """ & InputFilePath & """ is a folder. Only files are supported."
WScript.Quit 1
End If

If Not fs.FileExists(InputFilePath) Then
MsgBox "DupeFile.vbs: """ & InputFilePath & """ cannot be found."
WScript.Quit 1
End If

' ****** NEXT TWO LINES ARE NEW ******
Dim SourceFileObj
Set SourceFileObj = fs.GetFile(InputFilePath)

Dim LastDot
Dim LastSlash1
Dim LastSlash2

LastDot = InStrRev(InputFilePath, ".")
LastSlash1 = InStrRev(InputFilePath, "")
LastSlash2 = InStrRev(InputFilePath, "/")

Dim LeftPart
Dim RightPart

If LastDot > LastSlash1 And LastDot > LastSlash2 Then
LeftPart = Left(InputFilePath, LastDot - 1)
RightPart = Right(InputFilePath, Len(InputFilePath) - (LastDot - 1))
Else
LeftPart = InputFilePath
RightPart = ""
End If

Dim CurrentNum
Dim OutputFilePath
Dim StrNum

' ****** NEW LINE ******
Dim OutputFileObj

For CurrentNum = 1 To NumberOfCopies
StrNum = CStr(CurrentNum)

If Len(StrNum) < PadTo Then
	StrNum = String(PadTo - Len(StrNum), "0") & strNum
End If

OutputFilePath = LeftPart & "_" & StrNum & RightPart

' ****** NEW LINE ******
fs.CopyFile InputFilePath, OutputFilePath, False

Set OutputFileObj = fs.GetFile(OutputFilePath)

OutputFileObj.Attributes = SourceFileObj.Attributes

Next[/code]