PowerShell script for incremental backup using modified time

Last updated on 12th January 2017

Incremental backups copies only the files that are modified since the last backup. Here is a PowerShell script to take incremental backups of your files. You run the script by passing three parameters - the source location, destination location and number of days (n). The script scans the files recursively in the source location and sub-folders and gets the list files that were modified in the last N number of days and copies them over to the destination folder. All the three parameters are mandatory.

The Get-ChildItem and where-object cmdlets are piped together to filter out files in the source location whose LastWriteTime attribute is in the last N days. The value of N is passed to the script as a parameter.

After obtaining the list of files to be copied, we use a Foreach loop to iterate through each of them and check if the directory structure exist in the destination. If the directory doesn't exists, we create that directory using New-Item cmdlet. Split-path cmdlet extracts just the parent directory path from the full file path.

Once the directory structure is put in place, the files are copied from source to the destination path. To construct the destination file path we replace the source path string with the destination path string. The replace function is case sensitive, which is the reason why we convert all file paths to lowercase first.

FileBackup.ps1


<#

.SYNOPSIS
  Powershell script to backup files older than N days.
  
.DESCRIPTION
  This PowerShell script is for taking incremental backups of files modified in the last N days from the specified source to destination folder.
  
.PARAMETER <source>
   Source location where the files should be copied from.

.PARAMETER <destination>
   Target location where the files should be copied to.
    
 .PARAMETER <N days>
   Only files modified in the last N days will be copied.
 
.NOTES
  Version:        1.0
  Author:         Open Tech Guides
  Creation Date:  11-Jan-2017
 
.LINK
    www.opentechguides.com
    
.EXAMPLE
  FileBackup c:\source-folder d:\dest-folder 30
   
#>

Param(
  [Parameter(Mandatory=$true, position=0)][string]$source,
  [Parameter(Mandatory=$true, position=1)][string]$destination,
  [Parameter(Mandatory=$true, position=2)][Int]$days
)

$src = $source.toLower()
$dest = $destination.toLower()

Write-Host "File backup started."
Write-Host "Source: " $src 
Write-Host "Destination: " $dest 
Write-Host "Policy: Files older than" $days "days"

Write-Host "Scanning files ..."

$FilesToCopy = Get-ChildItem $src -force -recurse| where-object {($_.LastWriteTime -gt (Get-Date).AddDays(-$days))  -and  ($_.PSIsContainer -ne $True)}

Write-Host "Scanning completed."

Write-Host "Copying files..."
$count = 0
Foreach($File in $FilesToCopy)

{
    $src_file = $File.Fullname.tolower()
    $dst_file = $File.Fullname.tolower().replace($src, $dest)
    $dst_dir = Split-path -path $dst_file
 
     if (!(Test-Path -path $dst_dir) ) {
       Write-Host "`t Create directory " $dst_dir
       New-Item -path $dst_dir -type Directory | out-null
    }
    
    
    Copy-Item $src_file -Destination $dst_file
    $count++
}

Write-Host "File copy completed."
Write-Host $count "file(s) copied."

Write-Host "File backup completed."

Sample Output

PS C:\> .\FileBackup.ps1 C:\mysrcfolder C:\mydestfolder 30
File backup started.
Source:  c:\mysrcfolder
Destination:  c:\mydestfolder
Policy: Files older than 30 days
Scanning files ...
Scanning completed.
Copying files...
         Create directory  c:\mydestfolder\opt
         Create directory  c:\mydestfolder\sys
File copy completed.
5 file(s) copied.
File backup completed.

PS C:\>

Note: This script does not copy empty directories in source location as it only checks the modification timestamps of files and not directories.


Post a comment

Comments

Marvin | November 14, 2023 8:08 AM |

Copy-Item : ?????“Y:\home\marv\logseq\logseq\bak\journals\2023_11_09\2023-11-10t06_54_11.919z.desktop.md”?????????? ???? D:\workspace\powershell-scripts\file-backup.ps1:65 ??: 3 + Copy-Item $src_file -Destination $dst_file + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : ObjectNotFound: (Y:\home\marv\lo...919z.desktop.md:String) [Copy-Item], ItemNotFoundException

Marvin | November 14, 2023 7:07 AM |

Works like a charm! Thanks!

Riswan | May 11, 2020 7:28 AM |

"Get-ChildItem : The specified path, file name, or both are too long. The fully qualified file name must be less than 260 character.and directory name must be less than 260 character" error showing on above script. how to rectify the error

PS_Wiz | May 13, 2020 1:08 PM |

That's a restriction in Windows. A workaround is to use that filepath and Map a Network drive which will reduce the path and filename size.

Md. Mohashin Khan | October 2, 2017 3:30 PM |

Hi dear, How to run below powershell commmand by a task scheduler? PS C:\> .\FileBackup.ps1 C:\mysrcfolder C:\mydestfolder 30

Sammy | April 3, 2020 5:34 PM |

In the task scheduler click "Basic Task" and in the Create Basic Task Wizard enter your command in the start a program section with arguments.

Md. Mohashin Khan | October 2, 2017 3:30 PM |

HI Drear Where I'm set in script source location (c:\source-folder) and destination location(d:\dest-folder) day(30) and how to run "PS C:\> .\FileBackup.ps1 C:\mysrcfolder C:\mydestfolder 30" command by windows task scheduler.