Need help connecting to session and rename files – PowerShell

Advertisement

smcxviet
Joined:
Posts:
4

Need help connecting to session and rename files – PowerShell

Hello everyone, thank you in advance!

I was tasked to automate renaming/formatting file names on a SFTP server.
I have one system that uploads a file(s) to the server and then another system picks up that file to be processed. However since the filename is not in the correct format, the second system is unable to process the files.

I've written a PowerShell script (attached below) on how I want the filenames to be formatted/renamed. However I am having difficulty implementing it (Connecting to the SFTP server and running the script). I'm extremely unfamiliar with WinSCP (I only stumbled onto it because of the given task), and also SFTP for that matter, so any help would be greatly appreciated.
Last edited by smcxviet on 2018-12-19 19:40; edited 1 time in total
Description: Script to format filename

Reply with quote

Advertisement

smcxviet
Joined:
Posts:
4

RE:

I finally got the script to connect to the session (yes!). However, I encounter the following error:
Error: Exception calling "Substring" with "2" argument(s): "Index and length must refer to a location within the string.
Parameter name: length
I was able to test the renaming logic portion of the code without issue in PowerShell (using $FullArray = $FileName.split("."), but when I run it with the SFTP configuration, I get the above error. So I'm assuming that I'm calling/using some of the WinSCP Assembly incorrectly.

For example: $directory = $session.ListDirectory("/home/martin/public_html"), does that mean $directory is an array type variable?
Also, am I using the proper path to select files/folders on the server? That could explain why it keeps saying Index and length must refer to a location within the string.

Thanks again!
-Kevin
try
{
    # Load WinSCP .NET assembly
    Add-Type -Path 'C:\Program Files (x86)\WinSCP\WinSCPnet.dll'
 
    # Setup session options
    $sessionOptions = New-Object WinSCP.SessionOptions -Property @{
        Protocol = [WinSCP.Protocol]::sftp
        HostName = "hostname.com"
        UserName = "user"
        Password = "password"
        PortNumber = 2223
        SshHostKeyFingerprint = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
    }
 
    $session = New-Object WinSCP.Session
 
    try
    {
        # Connect
        $session.Open($sessionOptions)
 
        $directory = $session.ListDirectory("/chroothome/xxxx/ftproot/Kevin-Test")
 
        foreach ($fileInfo in $directory.Files) 
        {        
            #Copy file to draft folder for backup
            Copy-Item $fileinfo.FullName -Destination "/chroothome/xxxx/ftproot/Kevin-Test/draft"
            
            #Assigns filename to a variable to use for name processing
            $FileName = $fileInfo.Name
 
            #Splits FileName into 3 strings by delimiter "."
            $FullArray = $FileName.split(".")
 
            #Decreases length of FullArray[1] to desired length
            $FullArray[1] = $FullArray[1].substring(0,8)
 
            #Turns Date into a single Char array 
            $DateArray = $FullArray[1].ToCharArray()
 
            #Converts MMDDYY to MMDDYYYY
            $year1 = $DateArray[4]
            $year2 = $DateArray[5]
            $DateArray[4] = "2"
            $DateArray[5] = "0"
            $DateArray[6] = $year1
            $DateArray[7] = $year2
 
            #Joins DateArray back into a single string
            $FullArray[1] = $DateArray -join ""
 
            #Adds proper separators inbetween the strings 
            $FullArray = $FullArray[0] + "_" + $FullArray[1] + "." + $FullArray[2]
 
            #Parameters: (String Source path, string target path) Path to new location and Name to move/rename the file to
            $session.MoveFile($fileInfo.FullName, "/chroothome/xxxx/ftproot/Kevin-Test" + $FullArray)
        }
    }
    finally
    {
        # Disconnect, clean up
        $session.Dispose()
    }
 
    exit 0
}
catch
{
    Write-Host "Error: $($_.Exception.Message)"
    exit 1
}

Reply with quote

martin
Site Admin
martin avatar
Joined:
Posts:
41,253
Location:
Prague, Czechia

Re: RE:

Your code is probably failing on . and .. entries in the listing. You need to skip those.

A simple way to do that is by replacing this:
$directory = $session.ListDirectory("/chroothome/xxxx/ftproot/Kevin-Test") 
 
foreach ($fileInfo in $directory.Files)
with:
$fileInfos = $session.EnumerateRemoteFiles(
    "/chroothome/xxxx/ftproot/Kevin-Test", $Null,
    [WinSCP.EnumerationOptions]::None)
 
foreach ($fileInfo in $fileInfos)

Reply with quote

smcxviet
Joined:
Posts:
4

Happy New Year

Thank you for all your help Martin, I finally got the files to rename!

The last thing I'm trying to do now is create a copy/backup before renaming the files. The files are located in my /Kevin-Test folder and I want to copy them into my /Kevin-Test/draft folder. However, I am having trouble getting the files to copy.

I'm trying to use the following code (it's also the first line within my foreach loop); but it doesn't seem to work:
Copy-Item $fileinfo.FullName -Destination "//chroothome/xxxx/ftproot/Kevin-Test/draft"
and I get the following error:
copy-item : Cannot find path '//chroothome/xxxx/ftproot/Kevin-Test/Snfhc_users.080517090840.txt' because it does not exist.
At C:\Users\kdang\Desktop\File rename.ps1:33 char:13
+             copy-item $BackupFile -Destination "//chroothome/xxxx ...
+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (//chroothome/sn...80517090840.txt:String) [Copy-Item], ItemNotFoundException
    + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.CopyItemCommand
It seems like it's trying to search on my local computer, but I need it to search on the server. Am I targeting the file on the server incorrectly? For example: how would I target the file //chroothome/xxxx/ftproot/Kevin-Test/File123.txt within my session? Also, is (PowerShell) Copy-Item the correct command to use?

Thank you in advance,
Kevin D

Reply with quote

Advertisement

smcxviet
Joined:
Posts:
4

This is what I have so far:
$BackupSource = $fileInfo.FullName
$BackupTarget = "//chroothome/xxxx/ftproot/Kevin-Test/Draft/" + $fileInfo.Name
$session.DuplicateFile($BackupSource, $BackupTarget)
But, I keep getting the following error:
Error: Exception calling "DuplicateFile" with "2" argument(s): "Operation not supported."
I found this link ("DuplicateFile" method fails with "Operation not supported"), and I'm sure I'm connecting via SFTP. I also tried manually typing out the paths for $session.DuplicateFile, but no luck.

Reply with quote

martin
Site Admin
martin avatar

Most SFTP servers do not support remote file duplication either.
If your SFTP indeed does not support the duplication, you either have to download and reupload the file, or use shell interface (if available) instead.

Reply with quote

Advertisement

You can post new topics in this forum