Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Why Powershell outputing this table?

I’m a powershell noob. How come the following code is also outputing the table at the end after the "File to Delete" loop?

$stopwatch = [System.Diagnostics.Stopwatch]::StartNew()

# use partial hashes for files larger than 100KB:
# see documentation at: https://powershell.one/tricks/filesystem/finding-duplicate-files#finding-duplicate-files-fast

$result = Find-PSOneDuplicateFileFast -Path '\\READYNAS\Pictures\2020\10' #-Debug -Verbose
$stopwatch.Stop()

# output duplicates
$allFilesToDelete = @(foreach($key in $result.Keys)
    {
        #filters out the LAST item in the array of duplicates, because a file name of xxxx (0) comes before one without the (0)
        $filesToDelete = $result[$key][0..($result[$key].count - 2)]  

        #add each remaining duplicate file to table
        foreach($file in $filesToDelete)
        {        
            $file |
                Add-Member -MemberType NoteProperty -Name Hash -Value $key -PassThru | 
                Select-Object Hash, Length, FullName                         
        }
    }
)

$allFilesToDelete | Format-Table -GroupBy Hash -Property FullName | Out-String | Write-Host

$allFilesToDelete | Sort-Object -Property FullName -OutVariable allFilesToDelete

$allFilesToDelete | Format-Table -Property FullName | Out-String | Write-Host

$confirmation = Read-Host "Are you Sure You Want To Delete $($allFilesToDelete.count) files? (y/n)"
if ($confirmation -eq 'y') {
    $i = 0

    foreach($fileToDelete in $allFilesToDelete)
    {
        $i++
        Write-Host "$i File to Delete: $($fileToDelete.FullName)"
        #Remove-Item $file.FullName -Force -Verbose 4>&1 | % { $x = $_; Write-Host "Deleted file ($i) $x" }
    }
} else {
    Write-Host "User chose NOT to delete files!"
}

enter image description here

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

  • $allFilesToDelete | Sort-Object -Property FullName -OutVariable allFilesToDelete produces output (the input objects in the requested sort order), and since you’re not capturing or redirecting it, it prints to the host (display, terminal) by default.

    • It seems your intent is to sort the objects stored in $allFilesToDelete, which your command, does but it also produces output (the common -OutVariable parameter does not affect a cmdlet’s output behavior, it simply also stores the output objects in the given variable); you could simply assign the output back to the original variable, which wouldn’t produce any output:

      $allFilesToDelete = $allFilesToDelete | Sort-Object -Property FullName
      
    • In cases where actively suppressing (discarding) output is needed, $null = ... is the simplest solution:

  • Because the output results in implicitly Format-Table-formatted display representations (for custom objects that have no predefined formatting data), the subsequent Read-Host and Write-Host statements – surprisingly – print first.

    • The reason is that this implicit use of Format-Table results in asynchronous behavior: output objects are collected for 300 msecs. in an effort to determine suitable column widths.

    • The – suboptimal – workaround is to force pipeline output to print synchronously to the host (display), using Out-Host.

    • See this answer for details.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading