Making A Copy Of A Folder

Hi Michel,

I’m sure by now you wish you never got involved with this thread, but I still can’t get it to work in Windows. I try in Debug mode and as a compiled project under Windows 7 and nothing gets copied to the “Backups” folder. There are no errors, but nothing is there. It works great with the Mac, but not Windows. Here is your code that I’m using.

[code]Dim f As FolderItem
Dim d as Date
d= New Date
txtMarker.Text = "Backup "+ str(d.month) + " " + str(d.day) + " " + str(d.year) + " " + str(d.Hour) + " " + str(d.Minute) + " " + str(d.Second)
Dim M as String

M=txtMarker.Text

dim destination as FolderItem
dim destinationBackup as FolderItem

If TargetWin32 then
If DebugBuild Then
f = getfolderitem("").Parent.child(“Runs”)
destination =(getfolderitem("").parent.child(“Backups”).child(“Backup”))
destinationbackup =(getfolderitem("").parent.child(“Backups”).child(“Backup”))
else

  f = getfolderitem("").child("Runs")
  destination =(getfolderitem("").child("Backups").child("Backup"))
  destinationbackup =(getfolderitem("").child("Backups").child("Backup"))
End If

if f = nil or not f.exists then msgbox "oops"

dim s as new shell
s.execute "XCopy /E /I "+f.ShellPath+" "+destination.ShellPath+"\" +f.name

Msgbox "Links should have been copied to documents"
destination.Name=M

M=txtMarker.Text

elseIf TargetMacOS then

dim source as folderitem = getfolderitem("").child("Runs And Rosters 2.0")
if source <> nil and source.Exists then
   destination =(getfolderitem("").child("Backups").child("Backup"))
  source.CopyFileTo(destination)
  destination.Name=M
end if

End If[/code]

Hi James.

Here, with the project you posted which I modified to have the right paths, I find the folder I had put within Runs inside the Backup 7 18 2015 11 56 58 folder, after clicking on the button.

Of course with an empty Runs folder nothing will copy.

Maybe you need to check if Runs contains anything before creating the backup folder ?

Hi Michel,

With the last code I listed above and with a folder called Runs that contains two folders within that also contain images files, when I run the app under Windows 7 nothing is copied to the Backups folder. I don’t get any errors, but the files are not copied.

If you use the code I have posted above, are you able to get it to work under Windows 10?

[quote=201268:@James Redway]Hi Michel,

With the last code I listed above and with a folder called Runs that contains two folders within that also contain images files, when I run the app under Windows 7 nothing is copied to the Backups folder. I don’t get any errors, but the files are not copied.

If you use the code I have posted above, are you able to get it to work under Windows 10?[/quote]

I do not know what you did in you new code, but that broke it.

The previous project worked just fine.

You should go back to that version.

Hi Michel,

I’m sorry, but the previous code that you sent above under modified project does not work correctly. I just tried it again from a fresh download and ran it from Debug.

What it does is it renames the Runs folder to the Destination folder name in the root folder.

So I start with the folder “Runs” and end up with the folder Backup 7 18 2015 7 45 49 in the same directory. Runs is now gone. It just renames the “Runs” folder.

There is no file in the “Backups” folder.

[quote=201275:@James Redway]Hi Michel,

I’m sorry, but the previous code that you sent above under modified project does not work correctly. I just tried it again from a fresh download and ran it from Debug.

What it does is it renames the Runs folder to the Destination folder name in the root folder.

So I start with the folder “Runs” and end up with the folder Backup 7 18 2015 7 45 49 in the same directory. Runs is now gone. It just renames the “Runs” folder.

There is no file in the “Backups” folder.[/quote]

I will look into it when I get a chance.

Thanks Michel. I feel bad for taking up so much of your time. No rush. Have a great weekend.

OK. When something gets broken, you start over from the last version that worked, and you present both codes side by side to see what has been changed that did it. That is what I did.

This seems to do what you expect :
https://dl.dropboxusercontent.com/u/17407375/Copy%20Folder%206.xojo_binary_project

Thanks Michel,

I’m on vacation this week. I will take a look at it when I’m back at work next week. Thanks for taking the time to help. I really appreciate it.

Hi Michel,

I’m back from vacation and tried the code you posted. I hate to tell you this, but it does not work. It does not copy the folder to the Backups folder. It only renames the Backups folder with the file name that is assigned in the code. I compiled the app on a Mac for Windows and tested it on a Windows 7 machine. Its doing the same things as before, just renaming the Backups folder.

Perhaps you uploaded the wrong version? Sorry to be a pain in the butt.

[quote=204115:@James Redway]Hi Michel,

I’m back from vacation and tried the code you posted. I hate to tell you this, but it does not work. It does not copy the folder to the Backups folder. It only renames the Backups folder with the file name that is assigned in the code. I compiled the app on a Mac for Windows and tested it on a Windows 7 machine. Its doing the same things as before, just renaming the Backups folder.

Perhaps you uploaded the wrong version? Sorry to be a pain in the butt.[/quote]

It seemed to, work. I have forgotten now. I will have a look when I get a chance.

No rush. If you get a free moment. Thanks :slight_smile:

The example code you found in the language reference is not suitable for use in a real program.

Writing a function to copy directories is rather more complicated than many people realize. Here’s a function written for what I understand your situation to be.

Sub Backup(source as FolderItem, destination as FolderItem)
  if source is nil then
    dim e as new NilObjectException
    e.Message = "Backup failed.  source is nil."
    raise e
  end if
  if destination is nil then
    dim e as new NilObjectException
    e.Message = "Backup failed.  destination is nil."
    raise e
  end if
  
  if destination.Exists then
    dim e as new RuntimeException
    e.Message = "Backup failed.  destination directory already exists."
    raise e
  end if
  
  destination.CreateAsFolder
  if not destination.Directory then
    dim e as new RuntimeException
    e.Message = "Backup failed.  Unable to create destination directory."
    raise e
  end if
  
  dim items() as FolderItem
  dim count as Integer = source.Count
  for i as Integer = 1 to count
    dim item as FolderItem = source.TrueItem(i)
    if item <> nil then
      items.Append(item)
    end if
  next
  
  for each item as FolderItem in items
    if item.Directory then
      dim itemDest as FolderItem = destination.TrueChild(item.Name)
      Backup(item, itemDest)
    else
      item.CopyFileTo(destination)
      dim errorCode as Integer = item.LastErrorCode
      if errorCode <> 0 then
        dim e as new RuntimeException
        e.Message = "Backup failed.  Copy " + item.NativePath + " failed with error " + Str(errorCode) + "."
      end if
    end if
  next
End Sub

This code does its best to raise an exception if something goes wrong during the backup. Here’s how you might call Backup.

sub BackupRuns(runs as FolderItem, backupdir as FolderItem)
dim now as new Date
dim timestamp as String = now.SQLDateTime
dim destination as FolderItem = backupdir.TrueChild(runs.Name + “-” + timestamp)
try
Backup(runs, destination)
except e as RuntimeException
//handle backup failure as appropriate
end try
end sub

Hi Charles,

Thank you for posting the code. I saw something like this somewhere else on the forum, but I just don’t know how to implement it. Although I do my best, I don’t understand everything about Xojo, especially functions.

I was wondering, do you know of a simple example project that implements this code? For me that is the best way I can understand something.

[quote=205702:@James Redway]Hi Charles,

Thank you for posting the code. I saw something like this somewhere else on the forum, but I just don’t know how to implement it. Although I do my best, I don’t understand everything about Xojo, especially functions.

I was wondering, do you know of a simple example project that implements this code? For me that is the best way I can understand something.[/quote]

I’ve knocked out an example project. You can grab it from https://www.declaresub.com/files/BackupExample.zip .

something is wrong with your link

BackupExample

The link works in my browser. What appears to be wrong on your end?

Thank you Charles. I’m taking a look at it now.

The hyperlink does not work, but if you just copy the text into the browser it works fine. Just copy the text and paste it into a browser.

Why not let the system copy the files/folders instead of Xojo? The process is much quicker (less CPU and almost instantaneous…moreso than Xojo…You’ll notice it greatly if backing up a 1GB folder ;-)), and if the file is currently locked/in-use Xojo will yield an error about copying. The system, on the other hand, will copy the file regardless of lock state and no errors will occur.

  if source is nil then
    dim e as new NilObjectException
    e.Message = "Backup failed.  source is nil."
    raise e
  end if
  if destination is nil then
    dim e as new NilObjectException
    e.Message = "Backup failed.  destination is nil."
    raise e
  end if
  
  if destination.Exists then
    dim e as new RuntimeException
    e.Message = "Backup failed.  destination directory already exists."
    raise e
  end if
  
  destination.CreateAsFolder
  if not destination.Directory then
    dim e as new RuntimeException
    e.Message = "Backup failed.  Unable to create destination directory."
    raise e
  end if
  
  Dim buShell as new Shell
  
  //YAY no need for error handling during copy!!! Shell will duplicate the folder and files
  //even if the file is currently being used (locked); Xojo won't
  //Shell is also faster than Xojo!
  
  #if TargetWin32 then
    //Robocopy can copy any directory size; XCopy cannot!
    buShell.Execute "robocopy " + source.ShellPath + " " + destination.ShellPath + " /E"
  #else
    //Yay! Linux and Mac use the same command!
    //cp requires trailing slash at destination end...
    buShell.Execute "cp -r " + source.ShellPath + " " + destination.ShellPath + "/"
  #Endif

//Release resource in use...no longer needed.
buShell.close
  

The OP appeared to want a simple example.

You are mistaken to think that cp requires no error-handling; in case of a permissions problem, it will of course fail. In any case, a real backup implementation would require more verification, and I wouldn’t implement it using Xojo framework functions anyway.