I use the code below to copy a folder by recursion. Works fine, but exists a problem even least to me, because source folder label also is being included inside dest folder after copy, and i not want it. In this moment what happens is this:
SRC Folder:
C:\MyTest
-firstfolder
-secondfolder
-- secondfolderFile
DEST Folder (after copy):
C:\NewTest
-MyTest
-firstfolder
-secondfolder
-- secondfolderFile
And then i need that in dest folder only stays:
C:\NewTest
-firstfolder
-secondfolder
-- secondfolderFile
How make this using the following code?
program testCopyRecursion;
{$APPTYPE CONSOLE}
{$R *.res}
uses
Windows,
ShellAPI,
SysUtils;
function CopyFolder(const SrcFolder, DestFolder: String; iFileOp: Integer;
OverWrite: Boolean; ShowDialog: Boolean): Boolean;
var
MyFOStruct: TSHFileOpStruct;
Src, Dest: String;
ResultVal: Integer;
begin
Result := False;
Src := SrcFolder;
Dest := DestFolder;
if not DirectoryExists(Dest) then
ForceDirectories(Dest);
if (Src = '') or ((iFileOp <> FO_DELETE) and (Dest = '')) or
(CompareText(Src, Dest) = 0) then
Exit;
if Src[Length(Src)] = '\' then
SetLength(Src, Length(Src) - 1);
Src := Src + #0#0;
if (Dest <> '') and (Dest[Length(Dest)] = '\') then
SetLength(Dest, Length(Dest) - 1);
Dest := Dest + #0#0;
FillChar(MyFOStruct, SizeOf(MyFOStruct), 0);
with MyFOStruct do
begin
Wnd := 0;
wFunc := iFileOp;
pFrom := @Src[1];
pTo := @Dest[1];
fFlags := FOF_ALLOWUNDO or FOF_NOCONFIRMMKDIR;
if not OverWrite then
fFlags := fFlags or FOF_RENAMEONCOLLISION;
if not ShowDialog then
fFlags := fFlags or FOF_SILENT;
end;
try
MyFOStruct.fAnyOperationsAborted := False;
MyFOStruct.hNameMappings := nil;
ResultVal := ShFileOperation(MyFOStruct);
Result := (ResultVal = 0);
finally
end;
end;
begin
try
CopyFolder('C:\MyTest', 'C:\NewTest', FO_COPY, True, False);
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
Readln;
end.
You are copying the C:\MyTest
folder itself into the C:\NewTest
folder, rather than just copying what is inside of C:\MyTest
. Try setting the source path to 'C:\MyTest\*'
instead to copy only what is inside of C:\MyTest
.
And FYI, you don't need the call to ForceDirectories()
, as SHFileOperation()
creates the destination folder if it does not already exist. The documentation even says so:
Copy and Move operations can specify destination directories that do not exist. In those cases, the system attempts to create them and normally displays a dialog box to ask the user if they want to create the new directory. To suppress this dialog box and have the directories created silently, set the
FOF_NOCONFIRMMKDIR
flag infFlags
.
Try something more like this:
program testCopyRecursion;
{$APPTYPE CONSOLE}
{$R *.res}
uses
Windows, ShellAPI, SysUtils;
function CopyFolder(const SrcFolder, DestFolder: String;
OverWrite: Boolean; ShowDialog: Boolean): Boolean;
var
MyFOStruct: TSHFileOpStruct;
Src, Dest: String;
begin
Result := False;
if (SrcFolder = '') or (DestFolder = '') or
(CompareText(SrcFolder, DestFolder) = 0) then
Exit;
Src := IncludeTrailingPathDelimiter(SrcFolder) + '*'#0;
Dest := ExcludeTrailingPathDelimiter(DestFolder) + #0;
FillChar(MyFOStruct, SizeOf(MyFOStruct), 0);
with MyFOStruct do
begin
wFunc := FO_COPY;
pFrom := PChar(Src);
pTo := PChar(Dest);
fFlags := FOF_ALLOWUNDO or FOF_NOCONFIRMMKDIR;
if not OverWrite then
fFlags := fFlags or FOF_RENAMEONCOLLISION;
if not ShowDialog then
fFlags := fFlags or FOF_SILENT;
end;
Result := (SHFileOperation(MyFOStruct) = 0);
end;
begin
try
CopyFolder('C:\MyTest', 'C:\NewTest', True, False);
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
Readln;
end.