Differences

This shows you the differences between the selected revisions of the page.

library_example_recursive_search_text 2014-12-01 library_example_recursive_search_text 2025-04-10 (current)
Line 1: Line 1:
-===== Search recursively for text in remote directory / Grep files over SFTP/FTP protocol =====+====== Search recursively for text in remote directory / Grep files over SFTP/FTP protocol ======
-<code powershell> +The following script uses [[library|WinSCP .NET assembly]] from a [[library_powershell|PowerShell]] script. If you have another preferred language, you can easily translate it. 
-function SearchDirectory ($session, $path, $wildcard, $text)+ 
 +The script is distributed in WinSCP installer as a [[extension|WinSCP extension]]. 
 + 
 +To run the script manually use:  
 + 
 +<code> 
 +powershell.exe -File SearchText.ps1 -sessionUrl "sftp://username:password;fingerprint=ssh-rsa-xxxxxxxxxxx...@example.com/" -path "/path" -text "text" 
 +</code> 
 + 
 +See also [[library_example_listing_files_matching_wildcard|*]]. 
 + 
 +You can alter the script for other tasks, instead of grepping the matching files. You can for example [[library_session_removefiles|remove]] or [[library_session_getfiles|download]] the matching files. Just modify the action in the ''Action on match'' block accordingly. 
 + 
 +<code powershell - SearchText.ps1
 +# @name        &Search for Text... 
 +# @command      powershell.exe -ExecutionPolicy Bypass -File "%EXTENSION_PATH%" ^ 
 +#                  -sessionUrl "!E" -path "!/" -text "%Text%" -wildcard "%Wildcard%" ^ 
 +#                  -pause -sessionLogPath "%SessionLogPath%" 
 +# @description  Searches recursively for a text in the current remote directory 
 +# @version      8 
 +# @homepage    ~~SELF~~ 
 +# @require      WinSCP 5.16 
 +# @option      Text -run textbox "Text:" 
 +# @option      Wildcard -run textbox "File mask:" "*.*" 
 +# @option      SessionLogPath -config sessionlogfile 
 +# @optionspage  ~~SELF~~#options 
 + 
 +param ( 
 +    # Use Generate Session URL function to obtain a value for -sessionUrl parameter. 
 +····$sessionUrl = "sftp://user:mypassword;fingerprint=ssh-rsa-xxxxxxxxxxx...@example.com/", 
 +    [Parameter(Mandatory = $True)] 
 +····$path, 
 +    [Parameter(Mandatory = $True)] 
 +    $text, 
 +····$wildcard = "*.*", 
 + ···$sessionLogPath = $Null, 
 +    [Switch] 
 +    $pause 
 +) 
 + 
 +try
{ {
-    Write-Host ("Searching directory {0} ..." -f $path)+    if (!$text) 
 + ···
 +        throw "No Text was specified." 
 + ···}
-    $directoryInfo = $session.ListDirectory($path)+    # Load WinSCP .NET assembly 
 +····$assemblyPath = if ($env:WINSCP_PATH) { $env:WINSCP_PATH } else { $PSScriptRoot } 
 +    Add-Type -Path (Join-Path $assemblyPath "WinSCPnet.dll")
-    foreach ($fileInfo in $directoryInfo.Files)+    # Setup session options 
 +····$sessionOptions = New-Object WinSCP.SessionOptions 
 +····$sessionOptions.ParseUrl($sessionUrl) 
 + 
 +    $session = New-Object WinSCP.Session 
 + 
 +    try
    {     {
-        $filePath = ($path + &quot;/&quot; + $fileInfo.Name)· +        $session.SessionLogPath = $sessionLogPath 
-········ + 
-        if ($fileInfo.IsDirectory)+        # Connect 
 +        $session.Open($sessionOptions) 
 + 
 +        # Recursivelly enumerate files to grep 
 +········$fileInfos = 
 +············$session.EnumerateRemoteFiles( 
 +               $path, $wildcard, [WinSCP.EnumerationOptions]::AllDirectories
 + 
 +        foreach ($fileInfo in $fileInfos)
        {         {
-            # Skip references to current and parent directories +            # Action on match 
-            if (($fileInfo.Name -ne ".") -and + 
- ···············($fileInfo.Name -ne ".."))+            # Modify the code below if you want to do another task with 
 +            # matching files, instead of grepping their contents 
 + 
 + ···········if ($fileInfo.FileType -eq "L")
            {             {
-                # Recurse into subdirectory +                Write-Host &quot;Skipping symlink $($fileInfo.FullName)..."
-················SearchDirectory $session $filePath $wildcard $text+
            }             }
-        } +············else
-········else +
-        { +
-            # Does file name match wildcard? +
-            if ($fileInfo.Name -Like $wildcard)+
            {             {
-                Write-Host ("File {0} matches mask, searching contents..." -f $filePath) +                Write-Host "File $($fileInfo.FullName) matches mask, searching contents..." 
-                $tempPath = ($env:temp + "\" + $fileInfo.Name)+                $tempPath = (Join-Path $env:temp $fileInfo.Name)
                # Download file to temporary directory                 # Download file to temporary directory
 +                $filePath = [WinSCP.RemotePath]::EscapeFileMask($fileInfo.FullName)
                $transferResult = $session.GetFiles($filePath, $tempPath)                 $transferResult = $session.GetFiles($filePath, $tempPath)
-                # Did the download succeded?+                # Did the download succeeded?
                if (!$transferResult.IsSuccess)                 if (!$transferResult.IsSuccess)
                {                 {
Line 41: Line 99:
                    # Search and print lines containing "text".                     # Search and print lines containing "text".
                    # Use -Pattern instead of -SimpleMatch for regex search                     # Use -Pattern instead of -SimpleMatch for regex search
-                    Select-String -Path $tempPath -SimpleMatch $text+                    $matchInfo = Select-String -Path $tempPath -SimpleMatch $text 
 +                    # Print the results 
 +                    foreach ($match in $matchInfo) 
 +                    { 
 +                        Write-Host "$($fileInfo.FullName):$($match.LineNumber):$($match.Line)" 
 +                    }
                    # Delete temporary local copy                     # Delete temporary local copy
                    Remove-Item $tempPath                     Remove-Item $tempPath
Line 47: Line 110:
            }             }
        }         }
-    } 
-} 
- 
-try 
-{ 
-    # Load WinSCP .NET assembly 
-    Add-Type -Path "WinSCPnet.dll" 
-  
-    # Setup session options 
-    $sessionOptions = New-Object WinSCP.SessionOptions 
-    $sessionOptions.Protocol = [WinSCP.Protocol]::Sftp 
-    $sessionOptions.HostName = "example.com" 
-    $sessionOptions.UserName = "user" 
-    $sessionOptions.Password = "mypassword" 
-    $sessionOptions.SshHostKeyFingerprint = "ssh-rsa 2048 xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx" 
-  
-    $session = New-Object WinSCP.Session 
-     
-    $session.SessionLogPath = "session.log" 
-  
-    try 
-    { 
-        # Connect 
-        $session.Open($sessionOptions) 
-         
-        $remotePath = "/home/user" 
-        $wildcard = "*.txt" 
-        $text = "blah" 
-         
-        # Start recursive search 
-        SearchDirectory $session $remotePath $wildcard $text 
-  
    }     }
    finally     finally
Line 85: Line 116:
        $session.Dispose()         $session.Dispose()
    }     }
-· + 
-    exit 0+    $result = 0
} }
-catch [Exception]+catch
{ {
-    Write-Host $_.Exception.Message +    Write-Host "Error: $($_.Exception.Message)" 
-    exit 1+    $result = 1
} }
 +
 +# Pause if -pause switch was used
 +if ($pause)
 +{
 +    Write-Host "Press any key to exit..."
 +    [System.Console]::ReadKey() | Out-Null
 +}
 +
 +exit $result
</code> </code>
 +
 +===== [[options]] Options =====
 +
 +&screenshotpict(extension_recursive_search_text)
 +
 +In the //Text// box, specify the text to look for. The option is available when executing the extension only.
 +
 +In the //File mask// box, specify a [[file_mask|file mask]] to select files. The option is available when executing the extension only.
 +
 +In the //Session log file//, you can specify a path to a [[logging|session log file]]. The option is available on the [[ui_pref_commands|Preferences dialog]] only.
 +
 +In the //Keyboard shortcut//, you can specify a [[custom_key_shortcuts|keyboard shortcut]] for the extension. The option is available on the [[ui_pref_commands|Preferences dialog]] only.

Last modified: by martin