Windows Batch Script – Copy Files with Folder Structure

batchwindows

I want to copy files that have date modified attribute values within a specific date range from one folder to another. I'm able to perform the copy using the below script but it's only copying the root level files within the parent directory of the source location

I need to copy the entire folder structure for files meeting the date range requirement.

SET DESTINATION=c:\temp\new
SET DATE_FROM=01/01/2019
SET DATE_TO=01/10/2019

> nul forfiles /S /D +%DATE_FROM% /C "cmd /C if @isdir==FALSE 2> nul forfiles /M @file /D -%DATE_TO% && > con ( echo @path && copy /V @path %DESTINATION% )"

pause

This batch script copies all the files within the specified date range to the root of the C:\temp\new folder but it doesn't copy the source folder structure with it. I need the destination to also contain the matching source folder structure for copied files within the defined date range.

Best Answer

Copy Files and Folder Structure Recursively between a Date Range

You can use PowerShell and Get-ChildItem to get the LastWriteTime attribute values of files recursively in a starting source directory.

For the source files that have the LastWriteTime attribute value within the date range, you can replace the source folder value with the destination folder value, and then use Copy-Item with the -Recurse -Force parameters to create the matching structure and copy over the files.

Note: I wrote this in both batch script logic and PowerShell script logic below for you.


Batch

Important: Just set the topmost variable values (src= and dest=) for the source and destination folders, and also for the to and from date values for the range you need (Date_From= and Date_To=) in MM/DD/YYYY format as set in those values in the below script example.

SET "src=c:\source\original"
SET "dest=c:\temp\new"
SET "Date_From=01/01/2017"
SET "Date_To=02/26/2017"

CALL :PSScript "%src%" "%dest%" "%Date_From%" "%Date_To%"

SET PowerShellDir=C:\Windows\System32\WindowsPowerShell\v1.0
CD /D "%PowerShellDir%"
Powershell -ExecutionPolicy Bypass -Command "& '%PSScript%'"
IF EXIST "%PSScript%" DEL /Q /F "%PSScript%"
EXIT

:PSScript
SET PSScript=%temp%\~tmp%~n0.ps1
IF EXIST "%PSScript%" DEL /Q /F "%PSScript%"

ECHO $src       ^= "%~1";                                                                            >>"%PSScript%"
ECHO $dest      ^= "%~2";                                                                            >>"%PSScript%"
ECHO $Date_From ^= "%~3";                                                                            >>"%PSScript%"
ECHO $Date_To   ^= "%~4";                                                                            >>"%PSScript%" 

ECHO $Date_From ^=[datetime]$Date_From;                                                              >>"%PSScript%"
ECHO $Date_To   ^=[datetime]$Date_To;                                                                >>"%PSScript%"

ECHO $srcFiles ^= ^(Get-ChildItem -Path $src -Recurse^);                                             >>"%PSScript%"
ECHO $srcFiles ^| %% {If^(^($_.LastWriteTime -ge $Date_From^) -or ^($_.LastWriteTime -le $Date_To^)^)>>"%PSScript%"
ECHO                 {                                                                               >>"%PSScript%"
ECHO                     $dPath ^= ^($_.FullName.Replace^($src,$dest^)^);                            >>"%PSScript%"
ECHO                     Copy-Item $_.FullName -destination $dPath -Recurse -Force;                  >>"%PSScript%"
ECHO                 }                                                                               >>"%PSScript%"
ECHO               };                                                                                >>"%PSScript%"
GOTO :EOF

PowerShell

Important: Just set the topmost variable values ($src= and $dest=) for the source and destination folders, and also for the to and from date values for the range you need ($Date_From= and $Date_To=) in MM/DD/YYYY format as set in those values in the below script example.

$src  = "c:\source\original";
$dest = "c:\temp\new";
$Date_From = "01/01/2017";
$Date_To   = "02/26/2017";

$Date_From = [datetime]$Date_From;
$Date_To   = [datetime]$Date_To;

$srcFiles = (Get-ChildItem -Path $src -Recurse);
$srcFiles | % {If(($_.LastWriteTime -ge $Date_From) -or ($_.LastWriteTime -le $Date_To))
                {
                    $dPath = ($_.FullName.Replace($src,$dest));
                    Copy-Item $_.FullName -destination $dPath -Recurse -Force ; 
                }
              };

Further Resources

Related Question