My last week task was to copy shared folder content from one server to another server. This looks easy but it comes with following conditions:
- Copy content from Source to target folder( Ignore one folder (DfsPrivate) while copying content from source to target server)
- Copy source folder permission at all level while copying source to target folder and permission should not be restricted to source root folder. It means each source folder permission must match with target folder.
- Generate a report to cross verify source and target permission for all folder in source and target.
- Automate these step, so that it can be executed by end of every month (Should handle delta copy)
I decided to use PowerShell to automate these activities with Robocopy command.
You can download the .ps1 file attached below to skip further reading, however, if you are interested in knowing .ps1 file and wanted to tweak it based on your requirement then you have to read full blog Image may be NSFW.
Clik here to view.
Following are the methods in the .ps1 file corresponding to the activity mentioned above.
Image may be NSFW.
Clik here to view.
CopyFTPFolder.ps1 file accept three parameter 1) SourceFolderPath 2) TargetFolderPath and 3) Log folder path as shown in above screen.
You can download the .ps1 file and open it in inside Powershell ISE editor.
CopyContent is the method which used robocopy to copy the content from source to target.
- functionCopyContent([string]$sourcePath,[string]$targetPath,[string]$logPath)
- {
- $excludeFolderPath="$sourcePath\DfsPrivate"
- robocopy$sourcePath$targetPath/mir/sec/MT[:32]/XD$excludeFolderPath/Copy:DAT/DCOPY:T/z/np|tee$logPath
- }
Here are details of parameter passed to robocopy. You can modify them based on your requirement.
- /mir is used to copy all the content of source to target
- /Sec /Copy:DAT /DCOPY:T is used to copy the security, parameter
- /XD is used to exclude the copying of “DfsPrivate” folder.
- /MT[:32] will allow powershell script to use 32 thread while performing copying. You can set this value based on your server configuration.
- /Z will be used to perform delta copy.
- /np | tee $logPath will be used to log Robocopy activity and also show them on screen, so that user is aware of each activity instead of opening log file.
CopyACL function will copy the “Access Control List” of source folder to target folder.
- functionCopyACL($SourceFolderPath,$TargetFolderPath)
- {
- #COPY ACL
- Get-Acl$SourceFolderPath|Set-Acl$TargetFolderPath
- }
ExportPermissionfunction will iterate through each folder in given path and export ACL permission into csv file
- functionExportPermission($folderPath,$exportPath)
- {
- $allFolders=Get-ChildItem$folderPath-Recurse|? {$_.PSisContainer -eq$true}
- $collection= @()
- foreach ($folderin$allFolders)
- {
- $acl=Get-Acl$folder.FullName
- foreach ($entryin$acl.Access)
- {
- $object=New-ObjectPSObject-Property @{
- SourcePath=$folder.FullName
- SourceFileSystemRights=$entry.FileSystemRights
- SourceAccessControlType=$entry.AccessControlType
- SourceIdentityReference=$entry.IdentityReference
- SourceIsInherited=$entry.IsInherited
- SourceInheritanceFlags=$entry.InheritanceFlags
- SourcePropagationFlags=$entry.Propagationflags}
- $collection+=$object
- }
- }
- $collection|Export-Csv$exportPath
- }
Finally the Mainmethod which control the execution of this powershell script and calls above mentioned methods in a sequential order.
- functionMain($SourceFolderPath,$TargetFolderPath,$LogPath)
- {
- $timeStamp=(Get-Date).ToString()
- $timeStamp=$timeStamp.Replace("/","").Replace(":","").Replace(" ","")
- $timeLogPath="$LogPath\scriptLog_$timeStamp.txt"
- $CopyAclLogPath="$LogPath\CopyACLLog_$timeStamp.txt"
- $exportSourcePermissionPath="$LogPath\SourcePermission_$timeStamp.csv"
- $exportTargetPermissionPath="$LogPath\TargetPermission_$timeStamp.csv"
- $robocopyLogPath="$LogPath\RobocopyLog_$timeStamp.txt"
- #Perform Get Set ACL At Root level
- CopyACL$SourceFolderPath$TargetFolderPath
- Write-Host"Copying ACL permission from source to target (Only for root folder)...."
- #Robocopy Operation started
- $startTime=Get-Date
- CopyContent$SourceFolderPath$TargetFolderPath$robocopyLogPath
- $endTime=Get-Date
- $totalTimeTaken=NEW-TIMESPAN $startTime$endTime
- $str="Total time taken from $source to $target is $totalTimeTaken"
- Add-Content-Path$timeLogPath$str
- #Completed
- #Perform Get Set for each folder level
- $sourceRootDrive= ([regex]::matches($SourceFolderPath,"[a-zA-Z0-9]:","IgnoreCase")|%{$_.value})
- $targetRootDrive= ([regex]::matches($TargetFolderPath,"[a-zA-Z0-9]+","IgnoreCase")|%{$_.value})[0]
- $targetRootDrive="\\\cf5 $targetRootDrive"
- Write-Host"sourceRootDrive = $sourceRootDrive"
- Write-Host"targetRootDrive = $targetRootDrive"
- $allFolders=Get-ChildItem$SourceFolderPath-Recurse|? {$_.PSisContainer -eq$true}
- $collection= @()
- Write-Host"Copy ACL for each folder..."
- foreach ($folderin$allFolders)
- {
- $sourcePath=$folder.FullName
- $targetPath=$sourcePath.Replace("$sourceRootDrive","$targetRootDrive")
- CopyACL$sourcePath$targetPath
- Add-Content-path$CopyAclLogPath"'$sourcePath' ------'$targetPath'"
- Write-Output"'$sourcePath' ------'$targetPath'"
- Write-Progress-Activity"sourceRootDrive$ to $targetRootDrive"
- }
- #Completed
- #Export Permission For Source Folder
- Write-Host"Exporting Permission For Source Folder $SourceFolderPath"
- ExportPermission$SourceFolderPath$exportSourcePermissionPath
- #Completed
- #Export Permission For Target Folder
- Write-Host"Exporting Permission For Target Folder $TargetFolderPath"
- ExportPermission$TargetFolderPath$exportTargetPermissionPath
- #Completed
- }
Please fee free to comment and provide your value suggestion.
Note: This script must be executed from Source server only since regex used in Main method expect Drive path (G:\SomeFolderName) for source folder and network path (\\SomeServerName\SomeFolderName) for target path.
Image may be NSFW.Clik here to view.