darkoperator / Posh-SSH

PowerShell Module for automating tasks on remote systems using SSH
BSD 3-Clause "New" or "Revised" License
979 stars 226 forks source link

Get-SFTPChildItem No Longer Listing Files in 3.2.3 #592

Open roend83 opened 1 week ago

roend83 commented 1 week ago

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 *

darkoperator commented 1 week ago

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

roend83 commented 1 week ago

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 commented 1 week ago

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

roend83 commented 1 week ago

Same issue with 7.4.5 on the Windows 2022 Azure Pipeline

roend83 commented 1 week ago

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

darkoperator commented 1 week ago

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 commented 1 week ago

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

sberesinski commented 6 days ago

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.

darkoperator commented 6 days ago

@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 commented 5 days ago

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{}
}
ChrisRe-Lal commented 3 days ago

Hi, any news on a release?

darkoperator commented 3 days ago

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

ChrisRe-Lal commented 2 days ago

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

DarkLite1 commented 2 days ago

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

darkoperator commented 2 days ago

pushed 3.2.4 to the gallery with fix