Posh-SSH icon indicating copy to clipboard operation
Posh-SSH copied to clipboard

Get-SFTPChildItem No Longer Listing Files in 3.2.3

Open roend83 opened this issue 1 year ago • 16 comments

I think this is a similar issue to #590. Calling Get-SFTPChildItem without a Path parameter is not returning any results anymore. I'm pretty sure this was working in 3.2.0 but no longer works in 3.2.3. I've only tested this on Windows:

Get-SFTPChildItem -SessionId $session.SessionId -File -Verbose

This above command results no results, but if I add a Path parameter it returns the expected results:

Get-SFTPChildItem -SessionId $session.SessionId -File -Verbose -Path *

roend83 avatar Sep 11 '24 16:09 roend83

latest version on Windows image

image

Can you provide more info on the version of PS? if it is the deprecated Windows PowerShell or PowerShell 7, is it on Windows, Linux or MacOS and against what type of target. In the examples above it is against Linux

darkoperator avatar Sep 11 '24 17:09 darkoperator

I reproduced this on Powershell 7.4.5 on my local Windows machine and on a Windows 2022 Azure Pipeline using the latest installed version of Powershell (I'm not seeing the version in my logs).

roend83 avatar Sep 11 '24 17:09 roend83

It looks like the Azure Pipeline was using Windows PowerShell, I'll update it to PowerShell Core and try it again there.

roend83 avatar Sep 11 '24 17:09 roend83

Same issue with 7.4.5 on the Windows 2022 Azure Pipeline

roend83 avatar Sep 11 '24 17:09 roend83

Looks like I can reproduce this using PS 7.4.5 on Ubuntu 22.04 using WSL as well: image

roend83 avatar Sep 11 '24 17:09 roend83

so weird, I even installed it on my mac and I'm not able to replicate, but you have also used other hosts and are able

image image

Will build some clean VMs and test on those

darkoperator avatar Sep 11 '24 21:09 darkoperator

clean Windows 11. PS 7

image

PS 5.1

image image

I know it was an issue in 3.2.2, but still cant replicate in 3.2.3. My only options would be to ask if you would be willing to download the source and in VSCode set a breakpoint for the advanced function and step through it and see if that sheds any light

darkoperator avatar Sep 11 '24 21:09 darkoperator

Hi, I am experiencing same issue. I have two scripts getting files from different locations and the one that is getting files from root location (path '/') does not work, the one using path with additional folders '/test/' works correctly. I see same difference on your screenshots, looks like it is not getting files correctly when files are located at '/' path.

sberesinski avatar Sep 13 '24 09:09 sberesinski

@sberesinski thanks now I can reproduce. Starting to regret adding support for wildcards in path :(

Today is a busy day at work so it will have to wait until I have time in the weekend but a fix should be in by Monday

darkoperator avatar Sep 13 '24 13:09 darkoperator

Can you test this function to see if it behaves on your systems as it should

function Get-SFTPChildItem
{
    [CmdletBinding(DefaultParameterSetName='Index')]
    param(
        [Parameter(Mandatory=$true,
                   ParameterSetName = 'Index',
                   ValueFromPipelineByPropertyName=$true,
                   Position=0)]
        [Alias('Index')]
        [Int32[]]
        $SessionId,
        [Parameter(Mandatory=$true,
                   ParameterSetName = 'Session',
                   ValueFromPipeline=$true,
                   Position=0)]
        [Alias('Session')]
        [SSH.SFTPSession[]]
        $SFTPSession,
        [Parameter(Mandatory=$false,
                   Position=1)]
        [string]
        $Path = "",
        [Parameter(Mandatory=$false,
                   Position=2)]
        [Alias('Recursive')]
        [switch]
        $Recurse,
        [Parameter(Mandatory=$false,
                   Position=3)]
        [switch]
        $Directory,
        [Parameter(Mandatory=$false,
                   Position=4)]
        [switch]
        $File
     )
     Begin
     {
        function Get-SFTPItems
        {
            param($CurrentPath, $SFTPSession, [bool]$IsRecursive)
            
            try {
                Write-Verbose "Listing items in path: $CurrentPath"
                $items = $SFTPSession.Session.ListDirectory($CurrentPath)
                
                foreach ($item in $items) {
                    if (@('.','..') -notcontains $item.Name) {
                        if ((!$File -and !$Directory) -or ($File -and !$item.IsDirectory) -or ($Directory -and $item.IsDirectory))
                        {
                            $item
                        }
                        
                        if ($IsRecursive -and $item.IsDirectory) {
                            $subPath = if ($CurrentPath -eq '/') { "/$($item.Name)" } else { "$CurrentPath/$($item.Name)" }
                            Get-SFTPItems -CurrentPath $subPath -SFTPSession $SFTPSession -IsRecursive $true
                        }
                    }
                }
            }
            catch {
                Write-Error "Error listing items in $($CurrentPath): $_"
            }
        }

        function Split-SFTPPath
        {
            param([string]$Path)
            
            if ($Path -eq '/') {
                return @('/', '')
            }
            
            if ($Path -match '^(.*)/([^/]+)$') {
                $parentPath = if ($Matches[1] -eq '') { '/' } else { $Matches[1] }
                return @($parentPath, $Matches[2])
            }
            else {
                return @('/', $Path)
            }
        }

        $ToProcess = @()
        switch($PSCmdlet.ParameterSetName)
        {
            'Session'
            {
                $ToProcess = $SFTPSession
            }
            'Index'
            {
                foreach($session in $Global:SFTPSessions)
                {
                    if ($SessionId -contains $session.SessionId)
                    {
                        $ToProcess += $session
                    }
                }
            }
        }
     }
     Process
     {
        foreach($Sess in $ToProcess)
        {
            if ($Path -eq "") {
                $Path = $Sess.Session.WorkingDirectory
            }

            # Handle wildcards
            if ($Path -like "*[*?]*") {
                $pathParts = Split-SFTPPath -Path $Path
                $parentPath = $pathParts[0]
                $leafPattern = $pathParts[1]
                
                $items = Get-SFTPItems -CurrentPath $parentPath -SFTPSession $Sess -IsRecursive $false
                $items | Where-Object { $_.Name -like $leafPattern } | ForEach-Object {
                    if ($_.IsDirectory) {
                        $dirPath = if ($parentPath -eq '/') { "/$($_.Name)" } else { "$parentPath/$($_.Name)" }
                        Get-SFTPItems -CurrentPath $dirPath -SFTPSession $Sess -IsRecursive $Recurse
                    } else {
                        $_
                    }
                }
            }
            else {
                # Regular path (including root)
                Get-SFTPItems -CurrentPath $Path -SFTPSession $Sess -IsRecursive $Recurse
            }
        }
     }
     End{}
}

darkoperator avatar Sep 14 '24 11:09 darkoperator

Hi, any news on a release?

ChrisRe-Lal avatar Sep 16 '24 14:09 ChrisRe-Lal

Waiting for feedback on the function I pasted, if none I will post a release tomorrow

darkoperator avatar Sep 16 '24 15:09 darkoperator

I only tested your Test function with -Path * or without -Path both with or without -File and it seems to work on Windows

ChrisRe-Lal avatar Sep 17 '24 10:09 ChrisRe-Lal

Same issue with Get-SFTPChildItem not returning items on Windows. Thank you for looking into this as this was still working in 3.2.1

DarkLite1 avatar Sep 17 '24 12:09 DarkLite1

pushed 3.2.4 to the gallery with fix

darkoperator avatar Sep 17 '24 13:09 darkoperator

Seems to be working fine in 3.2.4 from our testing. I think this once can be closed.

DarkLite1 avatar Sep 23 '24 07:09 DarkLite1