Differences

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

library_example_recursive_search_text 2016-05-31 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 ======
-The following example uses [[library|WinSCP .NET assembly]] from a [[library_powershell|PowerShell]] script. If you have another preferred language, you can easily translate it.+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.
-//In the latest beta version//, the example is distributed in WinSCP installer as a [[extension|WinSCP extension]]. &beta+The script is distributed in WinSCP installer as a [[extension|WinSCP extension]].
-You can run the script (e.g. ''SearchText.ps1'') from WinSCP GUI using [[guide_custom_commands_automation|local custom command]]:+To run the script manually use:
<code> <code>
-powershell.exe -File SearchText.ps1 -sessionUrl "!S" -path "!/" -text "!?Text:?!" -pause+powershell.exe -File SearchText.ps1 -sessionUrl "sftp://username:password;fingerprint=ssh-rsa-xxxxxxxxxxx...@example.com/" -path "/path" -text "text"
</code> </code>
-See also [[library_example_listing_files_matching_wildcard|Listing files matching wildcard]].+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. 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.
- 
-===== In the Beta Version ===== 
-In the latest beta version, you can simplify the implementation by using ''[[library_session_enumerateremotefiles|Session.EnumerateRemoteFiles]]''. &beta 
<code powershell - SearchText.ps1> <code powershell - SearchText.ps1>
# @name        &Search for Text... # @name        &Search for Text...
-# @command      powershell.exe -ExecutionPolicy Bypass -File "%EXTENSION_PATH%" -sessionUrl "!S" -path "!/" -text "%Text%" -wildcard "%Wildcard%" -pause -sessionLogPath "%SessionLogPath%"+# @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 # @description  Searches recursively for a text in the current remote directory
-# @version      2+# @version      8
# @homepage    ~~SELF~~ # @homepage    ~~SELF~~
-# @require      WinSCP 5.8.4+# @require      WinSCP 5.16
# @option      Text -run textbox "Text:" # @option      Text -run textbox "Text:"
-# @option      Wildcard -run textbox "Wildcard:" "*.*" +# @option      Wildcard -run textbox "File mask:" "*.*" 
-# @option      SessionLogPath -config file "&Session log file:"+# @option      SessionLogPath -config sessionlogfile
# @optionspage  ~~SELF~~#options # @optionspage  ~~SELF~~#options
param ( param (
-    # Use Generate URL function to obtain a value for -sessionUrl parameter. +    # Use Generate Session URL function to obtain a value for -sessionUrl parameter. 
-    $sessionUrl = "sftp://user:mypassword;fingerprint=ssh-rsa-xx-xx-xx@example.com/", +    $sessionUrl = "sftp://user:mypassword;fingerprint=ssh-rsa-xxxxxxxxxxx...@example.com/", 
-    [Parameter(Mandatory)]+    [Parameter(Mandatory = $True)]
    $path,     $path,
-    [Parameter(Mandatory)]+    [Parameter(Mandatory = $True)]
    $text,     $text,
    $wildcard = "*.*",     $wildcard = "*.*",
    $sessionLogPath = $Null,     $sessionLogPath = $Null,
    [Switch]     [Switch]
-    $pause = $False+    $pause
) )
try try
{ {
 +    if (!$text)
 +    {
 +        throw "No Text was specified."
 +    }
 +
    # Load WinSCP .NET assembly     # Load WinSCP .NET assembly
    $assemblyPath = if ($env:WINSCP_PATH) { $env:WINSCP_PATH } else { $PSScriptRoot }     $assemblyPath = if ($env:WINSCP_PATH) { $env:WINSCP_PATH } else { $PSScriptRoot }
Line 74: Line 78:
            # matching files, instead of grepping their contents             # matching files, instead of grepping their contents
-            Write-Host ("File {0} matches mask, searching contents..." -f $fileInfo.FullName) +            if ($fileInfo.FileType -eq &quot;L&quot;)
-           $tempPath = (Join-Path $env:temp $fileInfo.Name) +
-            # Download file to temporary directory +
-            $transferResult = $session.GetFiles($session.EscapeFileMask($fileInfo.FullName), $tempPath) +
-            # Did the download succeeded? +
-            if (!$transferResult.IsSuccess)+
            {             {
-                # Print error (but continue with other files) +                Write-Host &quot;Skipping symlink $($fileInfo.FullName)..."
- ···············Write-Host $transferResult.Failures[0].Message+
            }             }
            else             else
            {             {
-                # Search and print lines containing "text". +                Write-Host "File $($fileInfo.FullName) matches mask, searching contents..." 
-                # Use -Pattern instead of -SimpleMatch for regex search +                $tempPath = (Join-Path $env:temp $fileInfo.Name)
-                $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 +
-                Remove-Item $tempPath +
-            } +
-        } +
-    } +
-    finally +
-    { +
-        # Disconnect, clean up +
-        $session.Dispose() +
-    } +
- +
-    $result = 0 +
-+
-catch [Exception] +
-+
-    Write-Host ("Error: {0}" -f $_.Exception.Message) +
-    $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> +
- +
-==== Options ==== +
- +
-In the //Text// box, specify the text to look for. +
- +
-In the //Wildcard// box, specify a [[file_mask|file mask]] to select files. +
- +
-In the //Session log file// you can specify a path to a [[logging|session log file]]. +
- +
-===== In the Stable Version ===== +
- +
-<code powershell> +
-param ( +
-    # Use Generate URL function to obtain a value for -sessionUrl parameter. +
-    $sessionUrl = "sftp://user:mypassword;fingerprint=ssh-rsa-xx-xx-xx@example.com/", +
-    [Parameter(Mandatory)] +
-    $path, +
-    [Parameter(Mandatory)] +
-    $text, +
-    $wildcard = "*.*", +
-    [Switch] +
-    $pause = $False +
-+
- +
-function SearchDirectory ($session, $path, $wildcard, $text) +
-+
-    Write-Host ("Searching directory {0} ..." -f $path) +
- +
-    $directoryInfo = $session.ListDirectory($path) +
- +
-    foreach ($fileInfo in $directoryInfo.Files) +
-    { +
-        $filePath = ($path + "/" + $fileInfo.Name)  +
-         +
-        if ($fileInfo.IsDirectory) +
-        { +
-            # Skip references to current and parent directories +
-            if (($fileInfo.Name -ne ".") -and +
-                ($fileInfo.Name -ne "..")) +
-            { +
-                # Recurse into subdirectory +
-                SearchDirectory $session $filePath $wildcard $text +
-            } +
-        } +
-        else +
-        { +
-            # Does file name match wildcard? +
-            if ($fileInfo.Name -Like $wildcard) +
-            { +
-                # Action on match +
- +
-                # Modify the code below if you want to do another task with +
-                # matching files, instead of grepping their contents +
- +
-                Write-Host ("File {0} matches mask, searching contents..." -f $filePath) +
-                $tempPath = ($env:temp + "\" + $fileInfo.Name)+
                # Download file to temporary directory                 # Download file to temporary directory
-                $transferResult = $session.GetFiles($session.EscapeFileMask($filePath), $tempPath)+                $filePath = [WinSCP.RemotePath]::EscapeFileMask($fileInfo.FullName) 
 +                $transferResult = $session.GetFiles($filePath, $tempPath)
                # Did the download succeeded?                 # Did the download succeeded?
                if (!$transferResult.IsSuccess)                 if (!$transferResult.IsSuccess)
Line 194: Line 103:
                    foreach ($match in $matchInfo)                     foreach ($match in $matchInfo)
                    {                     {
-                        Write-Host ($filePath + &quot;:&quot; + $match.LineNumber + &quot;:&quot; + $match.Line)+                        Write-Host "$($fileInfo.FullName):$($match.LineNumber):$($match.Line)"
                    }                     }
                    # Delete temporary local copy                     # Delete temporary local copy
Line 201: Line 110:
            }             }
        }         }
-    } 
-} 
- 
-try 
-{ 
-    # Load WinSCP .NET assembly 
-    Add-Type -Path "WinSCPnet.dll" 
-  
-    # Setup session options 
-    $sessionOptions = New-Object WinSCP.SessionOptions 
-    $sessionOptions.ParseUrl($sessionUrl) 
-  
-    $session = New-Object WinSCP.Session 
-     
-    try 
-    { 
-        # Connect 
-        $session.Open($sessionOptions) 
-         
-        # Start recursive search 
-        SearchDirectory $session $path $wildcard $text 
    }     }
    finally     finally
Line 228: Line 116:
        $session.Dispose()         $session.Dispose()
    }     }
-·+
    $result = 0     $result = 0
} }
-catch [Exception]+catch
{ {
-    Write-Host ("Error: {0}" -f $_.Exception.Message)+    Write-Host "Error: $($_.Exception.Message)"
    $result = 1     $result = 1
} }
Line 246: Line 134:
exit $result 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