Jump to content

Copy all files of a folder without overwriting existing ones


Go to solution Solved by Earthshine,

Recommended Posts

Goal: All files of a folder should be copied, but existing files should NOT be overwritten.

First I tried DirCopy(), but with the flag $FC_NOOVERWRITE no files are copied if the destination folder exists. Then I thought that it must be ok for DirCopy not to overwrite if the destination folder exists.

So I tried FileCopy(), also with the $FC_NOOVERWRITE flag, thinking that FileCopy would only not overwrite existing files. But unfortunately it doesn't work! Also FileCopy does not copy anything if the destination folder exists and the flag $FC_NOOVERWRITE is set.

In my opinion, with the $FC_NOOVERWRITE flag, FileCopy should only skip existing files, but not abort if the destination folder exists.

Here is a minimalistic test code. Before running the code in @TempDir create the folder "MyDocsSource" and in it a few files. The destination folder will be created automatically.

#include <FileConstants.au3>


;  DirCopy(@TempDir & "\MyDocsSource", @TempDir & "\MyDocsDest", $FC_OVERWRITE) ; <= All files are copied/overwritten.
; DirCopy(@TempDir & "\MyDocsSource", @TempDir & "\MyDocsDest", $FC_NOOVERWRITE) ; <= Nothing is copied if the destination folder exists.


; FileCopy(@TempDir & "\MyDocsSource\*.*", @TempDir & "\MyDocsDest", $FC_OVERWRITE + $FC_CREATEPATH) ; <= All files are copied/overwritten.
FileCopy(@TempDir & "\MyDocsSource\", @TempDir & "\MyDocsDest", $FC_CREATEPATH) ; <= Nothing is copied if the destination folder exists.


; Display the temporary directory.
; ShellExecute(@TempDir)

How to solve the problem?

Link to comment
Share on other sites

I just fully tested it from the example file code and it works perfectly. only copies files that don't exist so I don't know what your issue is.

#include <FileConstants.au3>
#include <MsgBoxConstants.au3>
#include <WinAPIFiles.au3>

Example()

Func Example()
    ; Create a constant variable in Local scope of the filepath that will be read/written to.
    Local Const $sFilePath = _WinAPI_GetTempFileName(@TempDir)

    ; Create a temporary file to copy.
    If Not FileWrite($sFilePath, "This is an example of using FileCopy.") Then
        MsgBox($MB_SYSTEMMODAL, "", "An error occurred whilst writing the temporary file.")
        Return False
    EndIf

    ; Copy Au3 files in the temporary directory to a new folder/directory called Au3Files.
    FileCopy(@TempDir & "\*.au3", @TempDir & "\Au3Files\", $FC_NOOVERWRITE + $FC_CREATEPATH)

    ; Display the temporary directory.
    ShellExecute(@TempDir)
EndFunc   ;==>Example

100% works. I even edited the some of the files in the source dir that already existed in the TEMP dir after the initial run to populate the target directory. As expected, FileCopy only copied files that did not exist because my edits were missing from the target dir files that were previously copied there by the initial run of the code.

My resources are limited. You must ask the right questions

 

Link to comment
Share on other sites

In the example from the help, I don't understand what the temp file is created for. It is not an .au3 file and is not copied.

24 minutes ago, Earthshine said:

only copies files that don't exist so I don't know what your issue is.

- If the destination folder does NOT exist and I run FileCopy, the destination folder is created and all files from the source folder are copied to the destination folder.
- Now the destination folder exists.
- Then I add more files in the source folder.
- Now when I run FileCopy, NO files are copied.

Link to comment
Share on other sites

18 minutes ago, Professor_Bernd said:

- Now when I run FileCopy, NO files are copied.

This is true (at least for my older AutoIt version 3.3.14.0). The following post by Melba23 explains the problem :

https://www.autoitscript.com/forum/topic/176952-filecopy-works-only-with-overwrite-solved/?do=findComment&comment=1270166

Excerpt :

Quote

If you copy files with a wildcard it will fail if there already are files with the same name and you do not specify that they should be overwritten. As AutoIt just uses the Windows API to do the job, it suffers from the same limitation.

 

Musashi-C64.png

"In the beginning the Universe was created. This has made a lot of people very angry and been widely regarded as a bad move."

Link to comment
Share on other sites

Here is an example that may show the problem better. :)

#include <FileConstants.au3>
#include <MsgBoxConstants.au3>
#include <WinAPIFiles.au3>

Example()

Func Example()
    Local $sFilePath

    ; Creates the source folder.
    DirCreate(@TempDir & "\MySourceDir\")

    For $i = 1 to 3
      ; Create a variable in Local scope of the filepath that will be read/written to.
      $sFilePath = _WinAPI_GetTempFileName(@TempDir & "\MySourceDir\")

      ; Create a temporary file to copy.
      If Not FileWrite($sFilePath, "This is an example of using FileCopy.") Then
          MsgBox($MB_SYSTEMMODAL, "", "An error occurred whilst writing the temporary file.")
          Return False
      EndIf
    Next

    ; Should copy all files from the source folder to the destination folder without overwriting existing files.
    FileCopy(@TempDir & "\MySourceDir\*.*", @TempDir & "\MyDestDir\", $FC_NOOVERWRITE + $FC_CREATEPATH)

    ; But it does not do that for me. When I start the script and the destination folder does NOT exist,
    ; there are 3 files in the source folder and all 3 files are copied to the destination folder.
    ;
    ; If I then start the script again and the destination folder now exists, there are 3 files in the source folder
    ; and NONE are copied to the destination folder. In the destination folder are only the previous 3 files.
    ;
    ; Each time I run the script again, there are more files in the source folder, but there are still 3 files
    ; in the destination folder.

    ; Display the temporary directory.
    ShellExecute(@TempDir)
EndFunc   ;==>Example

 

Link to comment
Share on other sites

if there are 3 files in the input directory and they are the same on the second run, then of course no files will be copied. They already exist! Add NEW files to source and try again.

My resources are limited. You must ask the right questions

 

Link to comment
Share on other sites

15 minutes ago, Musashi said:

If you copy files with a wildcard it will fail if there already are files with the same name and you do not specify that they should be overwritten. As AutoIt just uses the Windows API to do the job, it suffers from the same limitation.

Oh no! So that means if I copy 1,001 files via wildcards and only one file is already present, the 1,000 not present will NOT be copied. 🤦‍♂️

Does anyone know another short command I can use with "/AutoIt3ExecuteLine" to copy all files from a source folder that are not present in the destination folder without overwriting?

Many thanks to @Musashi for the information! 👍

Link to comment
Share on other sites

why on earth are you looping? and using *.* includes .TMP files that must get created with FileCopy.

 

use wildcards like this *.txt *.au3, etc..

 

this code is not needed at ALL

 

    For $i = 1 to 3
      ; Create a variable in Local scope of the filepath that will be read/written to.
      $sFilePath = _WinAPI_GetTempFileName(@TempDir & "\MySourceDir\")

      ; Create a temporary file to copy.
      If Not FileWrite($sFilePath, "This is an example of using FileCopy.") Then
          MsgBox($MB_SYSTEMMODAL, "", "An error occurred whilst writing the temporary file.")
          Return False
      EndIf
    Next
take that out of there no need to create the source dir 3 TIMES!
Edited by Earthshine

My resources are limited. You must ask the right questions

 

Link to comment
Share on other sites

here is your code I modified and it works, but it includes a TMP file that gets created when run. I think it's because you use *.* 

anyway, try this.

#include <FileConstants.au3>
#include <MsgBoxConstants.au3>
#include <WinAPIFiles.au3>

Example()

Func Example()
    Local $sFilePath

    ; Creates the source folder.

    ; Create a variable in Local scope of the filepath that will be read/written to.
    $sFilePath = _WinAPI_GetTempFileName(@TempDir & "\MySourceDir\")

    ; Should copy all files from the source folder to the destination folder without overwriting existing files.
    FileCopy(@TempDir & "\MySourceDir\*.*", @TempDir & "\MyDestDir\", $FC_NOOVERWRITE + $FC_CREATEPATH)

    ; Display the temporary directory.
    ShellExecute(@TempDir)
EndFunc   ;==>Example

 

My resources are limited. You must ask the right questions

 

Link to comment
Share on other sites

One way to copy files, but not overwrite existing files in the destination folder :

Local $hSearch, $sSourceDir, $sDestinationDir, $sFileName
$sSourceDir      = @ScriptDir & "\Source\"
$sDestinationDir = @ScriptDir & "\Destination\"
$hSearch = FileFindFirstFile($sSourceDir & "*.*")

; Check, if Destination folder exists. If not, then create it :
If Not StringInStr(FileGetAttrib($sDestinationDir), "D") Then DirCreate($sDestinationDir)
While True
    $sFileName = FileFindNextFile($hSearch)
    If @error Then ExitLoop
    If (Not FileExists($sDestinationDir & $sFileName)) And (Not StringInStr(FileGetAttrib($sSourceDir & $sFileName), "D")) Then
        FileCopy($sSourceDir & $sFileName, $sDestinationDir)
    EndIf
WEnd
FileClose($hSearch)

 

Musashi-C64.png

"In the beginning the Universe was created. This has made a lot of people very angry and been widely regarded as a bad move."

Link to comment
Share on other sites

I also tried :

#include <WinAPIShellEx.au3>
_WinAPI_ShellFileOperation (@ScriptDir & "\Source\*.*", @ScriptDir & "\Destination\", $FO_COPY, BitOR($FOF_SILENT, $FOF_NOCONFIRMATION))
ConsoleWrite("Error=" & @error & "  Extended=" & @extended & @CRLF) ; *** just a message

but there doesn't seem to be a flag for "not overwrite existing files"  :(

Musashi-C64.png

"In the beginning the Universe was created. This has made a lot of people very angry and been widely regarded as a bad move."

Link to comment
Share on other sites

Ok, I modified the sample code again. The 

#include <FileConstants.au3>
#include <MsgBoxConstants.au3>
#include <WinAPIFiles.au3>

Example()

Func Example()
    Local $sFilePath

    ; Creates the source folder.


    ; Should copy all files from the source folder to the destination folder without overwriting existing files.
    FileCopy(@TempDir & "\MySourceDir\*.*", @TempDir & "\MyDestDir\", $FC_NOOVERWRITE + $FC_CREATEPATH)

    ; Display the temporary directory.
    ShellExecute(@TempDir)
EndFunc   ;==>Example

the line of code

    $sFilePath = _WinAPI_GetTempFileName(@TempDir & "\MySourceDir\")

you DO NOT NEED!!! it creates a temp file and was used in the example just to create a file to copy. DO NOT USE THAT FUNCTION and you will not get .TMP files in your dest directory

Edited by Earthshine

My resources are limited. You must ask the right questions

 

Link to comment
Share on other sites

4 minutes ago, Earthshine said:

why on earth are you looping?

Please excuse me, but I don't understand what you want. In the loop I create 3 temp files. In each pass a temp name is created and then the temp file. 3 passes = 3 temp files.

6 minutes ago, Earthshine said:

take that out of there no need to create the source dir 3 TIMES!

Where do you see that the source folder is created 3x? There are 3 temp files created, no folder!

 

12 minutes ago, Earthshine said:

why on earth are you looping? and using *.* includes .TMP files that must get created with FileCopy. use wildcards like this *.txt *.au3, etc..

How else can you copy all the files?

Link to comment
Share on other sites

I was testing using real .au3 files. not using temp files. See my last post with the proper code for your example that does work perfectly

I just create that dir in TEMP and put 3 files in it. run the example, note the output dir has those three files.

add two more files to source dir. edit the other three that were there so that they are different from what was copied in run 1. that way you can test the output files to make sure they are not overwritten.

I think you confuse yourself alot of the times.

oh and ALL the files are copied by the single FileCopy statement. that is how to copy ALL files.

Edited by Earthshine

My resources are limited. You must ask the right questions

 

Link to comment
Share on other sites

1 minute ago, Professor_Bernd said:

From the help file: $FC_CREATEPATH (8) = Create destination directory structure if it doesn't exist

just get it out of there. use the code i posted above and test it. If you don't want to do that then I am done. Later.

My resources are limited. You must ask the right questions

 

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...