0

I am no expert in PowerShell and apologies if my script is way off but I really could use some help on this. I appreciate any help!!

I need to copy ONLY '.bak' files from a Server with folder structure like...

  • C:\test\Dell\Dell01.bak -DATE_Modified 5/18/2024

  • C:\test\Dell\Dell02.bak -DATE_Modified 5/19/2024

  • C:\test\Dell\file01.txt

  • C:\test\Dell\file02.txt

  • C:\test\HP\HP01.bak -DATE_Modified 5/16/2024

  • C:\test\HP\HP02.bak -DATE_Modified 5/17/2024

  • C:\test\HP\file01.txt

  • C:\test\HP\file02.txt

...to another Server and put the file in the SAME Folder Name from its original folder. There's one caveat. I ONLY want to copy the ONE .bak file with the MOST CURRENT DATE, hence why I put the -DATE_Modified above.

The script I have mostly works. The script does create the respective folders on the destination Server. It also ONLY copies the file with the MOST current date as expected.

The problem I'm running into is it ONLY copies the last file in the loop (in this example: HP02.bak -DATE_Modified 5/17/2024 (which is the correct file)) to the destination Server BUT it only copies that ONE file to BOTH folders, which is not entirely correct. It does NOT copy Dell02 at all.

Results that's partially WRONG:

Destination - \servername\D:\Backup\Dell\HP02.bak -DATE_Modified 5/17/2024 <---WRONG Destination - \servername\D:\Backup\HP\HP02.bak -DATE_Modified 5/17/2024 <-- Correct

The expected results should be:

Destination - \servername\D:\Backup\Dell\Dell02.bak -DATE_Modified 5/19/2024

Destination - \servername\D:\Backup\HP\HP02.bak -DATE_Modified 5/17/2024

NOTE: There are hundreds of Subfolders after C:\Test\ so I need to use a Wildcard in the path.

NOTE: The file names in this example that end in '01' and '02' are only examples. The actual file names are much longer and include long hash numbers.

Script:
$Domain_Username = "domain\username"
$Domain_Password = "xxxxxxxxxxxxxxxxxxx" 

$Password_Securestring = New-Object -TypeName System.Security.SecureString
$Domain_Password.ToCharArray() | ForEach-Object {$Password_Securestring.AppendChar($_)}
$Credentials = New-Object -Typename System.Management.Automation.PSCredential -argumentlist    $Domain_Username, $Password_Securestring

$Servers = Get-Content "C:\Scripts\Get-Content\Servers.txt"

$Remote_Source_Folder = "C$\Test"
$Remote_Source_File = "C$\Test\*\*.bak"

$Temp_Dest = "\\Destination_Server\D`$\Backup"

foreach ($Server in $Servers){
          $Source_Folder = "\\$Server\$Remote_Source_Folder"
          $Source_File = "\\$Server\$Remote_Source_File"
          Write-Host $Source_Folder
          Write-Host $Source_File
          $foldernames = Get-ItemPropertyValue -Path $Source_Folder\* -Name Name
          New-PSDrive -Name Y -PSProvider FileSystem -Root $Source_Folder -Credential $Credentials | Out-Null
          New-PSDrive -Name Z -PSProvider FileSystem -Root $Temp_Dest -Credential $Credentials | Out-Null
      
        foreach ($foldername in $foldernames){
                  write-host $foldername
                  $DestPath = Join-Path "$Temp_Dest" "$foldername" 
                  if ( ! ( Test-Path $DestPath )) {mkdir $DestPath | out-null} 
                  $DestPath
               
        $Files = Get-ChildItem $Source_Folder\* -Recurse 
        foreach ($File in $Files){
                  Get-ChildItem $File -File | ForEach-Object {Get-ChildItem $Source_File -File | Sort-Object -Property LastWriteTime `
              | Select-Object -Last 1 | Copy-Item -Destination $DestPath -Recurse}
                 }
             }
          Remove-PSDrive -Name Y    
          Remove-PSDrive -Name Z
    }

1 Answer 1

0

After re-writing part of the script I managed to solve the issue.

Script purpose: Authenticate and map a drive to a remote (source) server and do the same to a destination server. Then, from source, copy specific files based on 'lastwritetime' (because there are multiple files in the dir with same *.bak name) to their respective folder (which is also created) in the destination location. I only want to copy files in each subfolder with *.bak that has the MOST recent date.

Here is the new script:

$Domain_Username = "domain\username"
$Domain_Password = "xxxxxxxxxxxxxxxxxxx" 

$Password_Securestring = New-Object -TypeName System.Security.SecureString
$Domain_Password.ToCharArray() | ForEach-Object 
{$Password_Securestring.AppendChar($_)}
$Credentials = New-Object -Typename System.Management.Automation.PSCredential -argumentlist    $Domain_Username, 
$Password_Securestring

$Servers = Get-Content "C:\Scripts\Get-Content\Servers.txt"

$Remote_Source_Folder = "C$\Test"
$Remote_Source_File = "C$\Test\*\*.bak"

$Temp_Dest = "\\Destination_Server\D`$\Backup"

foreach ($Server in $Servers){
          $Source_Folder = "\\$Server\$Remote_Source_Folder"
          $Source_File = "\\$Server\$Remote_Source_File"
          Write-Host $Source_Folder
          Write-Host $Source_File
          $foldernames = Get-ItemPropertyValue -Path $Source_Folder\* -Name Name
      New-PSDrive -Name Y -PSProvider FileSystem -Root $Source_Folder -Credential $Credentials | Out-Null
      New-PSDrive -Name Z -PSProvider FileSystem -Root $Temp_Dest -Credential $Credentials | Out-Null
  
        try {
        $Folders = Get-ChildItem $Source_Folder -Directory
        foreach ($Folder in $Folders) {
            $DestPath = Join-Path $Temp_Dest $Folder.Name
            if (-not (Test-Path $DestPath)) {
                New-Item -ItemType Directory -Path $DestPath | Out-Null
            }

            $Files = Get-ChildItem $Folder.FullName -File | Sort-Object -Property LastWriteTime | Select-Object -Last 1 
            foreach ($File in $Files) {
                Copy-Item -Path $File.FullName -Destination $DestPath -Force
            }
        }
    } finally {
        # Remove mapped drives
          Remove-PSDrive -Name Y
          Remove-PSDrive -Name Z
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for contributing to the Stack Overflow community. This may be a correct answer, but it’d be really useful to provide additional explanation of your code so developers can understand your reasoning. This is especially useful for new developers who aren’t as familiar with the syntax or struggling to understand the concepts. Would you kindly edit your answer to include additional details for the benefit of the community?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.