0

can someone please help me. Still new to powershell, I am comparing my documents and desktop mirror to check my backup solutions using several different codes. The one below is meant to check both the documents/desktop with its mirror folders and tell me exactly what files are 'different' between source and destination and output it into the same output.txt file (not sure if it overwrites it). When I do this for my documents alone, it works when I want try the code for my desktop it doesn't output anything at all. Any advice?

function Get-Directories ($path)
{
    $PathLength = $path.length
    Get-ChildItem $path -exclude *.pst,*.ost,*.iso,*.lnk | % {
        Add-Member -InputObject $_ -MemberType NoteProperty -Name RelativePath -Value $_.FullName.substring($PathLength+1)
        $_
    }
}

Compare-Object (Get-Directories $Folder3) (Get-Directories $Folder4) -Property RelativePath | Sort RelativePath, Name -desc | Out-File  C:\Users\desktop\output.txt
mklement0
  • 382,024
  • 64
  • 607
  • 775
Yaz
  • 23
  • 6

2 Answers2

1

since you're not using -Recurse when listing files, you could just use the file name instead of adding on a relative path property:

$folder1 = gci 'C:\Users\username\desktop' -exclude *.pst,*.ost,*.iso,*.lnk
$folder2 = gci 'D:\desktop' -exclude *.pst,*.ost,*.iso,*.lnk
Compare-Object $folder1 $folder2 -Property Name,Length

Name     Length SideIndicator
----     ------ -------------
test.txt    174 =>           
test.csv    174 <=           

# Alternatively, use -PassThru to keep the whole object:
Compare-Object $folder1 $folder2 -Property Name,Length -PassThru | select SideIndicator,FullName,Length,LastWriteTime

SideIndicator FullName                  Length LastWriteTime       
------------- --------                  ------ -------------       
=>            D:\desktop                   174 7/14/2021 2:47:09 PM
<=            C:\Users\username\desktop    174 7/14/2021 2:47:09 PM

Use Out-File -Append to append output to a file.


As for troubleshooting your current script, try manually checking whether the RelativePath property looks like it's getting set correctly for you:

(Get-Directories $Folder3).RelativePath
(Get-Directories $Folder4).RelativePath

Finally, I recommend using robocopy over powershell for backup stuff like this, since it can use backup privileges (for locked files) and can copy multiple files at a time, but it's personal preference:

robocopy source destination /b /mir /mt /r:0 /w:0

/b - Runs robocopy in backup mode. Will copy everything as long as you are an Administrator
/mir - Mirrors everything from the source to the destination
/mt - Copies up to 8 files at a time
/r:0 - Sets it to not retry a file, default is like a million retries
/w:0 - Sets the time to 0 seconds between retries - default is like 30 seconds

source: https://community.spiceworks.com/topic/286190-transfer-user-profiles-using-robocopy

Cpt.Whale
  • 4,784
  • 1
  • 10
  • 16
  • thank you so so much I will give this a go tonight, sorry where does the out-file -append go into the script? do you pipe it in at the end | Out-File -Path -Append like this? – Yaz Jul 15 '21 at 16:59
  • @Yaz yeah: `$stuff | Out-File -Path 'C:\path\to\output.txt' -Encoding utf8 -Append` – Cpt.Whale Jul 15 '21 at 17:49
1

Judging by earlier revisions of your question, your problem wasn't that your code didn't output anything at all, but that the output had empty Name property values.

Thus, the only thing missing from your code was Compare-Object's -PassThru switch:

Compare-Object -PassThru (Get-Directories $Folder3) (Get-Directories $Folder4) -Property RelativePath | 
  Sort RelativePath, Name -desc | 
    Out-File C:\Users\desktop\output.txt

Without -PassThru, Compare-Object outputs [pscustomobject] instances that have a .SideIndicator property (to indicate which side a difference object is exclusive to) and only the comparison properties passed to -Property.

  • That is, in your original attempt the Compare-Object output objects had only .SideIndicator and .RelativePath properties, and none of the other properties of the original [System.IO.FileInfo] instances originating from Get-ChildItem, such as .Name, .LastWriteTime, ...

With -PassThru, the original objects are passed through, decorated with an ETS (Extended Type System) .SideIndicator property (decorated in the same way you added the .RelativePath property), accessing the .Name property later works as intended.

Note:

  • Since Out-File then receives the full (and decorated) [System.IO.FileInfo] instances, you may want to limit what properties get written via a Select-Object call beforehand.
    Additionally you may choose a structured output format, via Export-Csv for instance, given that the formatting that Out-File applies is meant only for the human observer, not for programmatic processing.

  • $_.FullName.substring($PathLength+1) in your Get-Directories should be $_.FullName.substring($PathLength), otherwise you'll cut off the 1st char.

mklement0
  • 382,024
  • 64
  • 607
  • 775