3

I’m new to PowerShell and am trying to convert a batch file that downloads multiple files based on names and extension from a directory on an ftp site. While I’ve found several examples that download a file, I’m struggling to find one that shows how to download multiple files. In a batch I can quite simply use the ftp.exe and the mget command with wildcards??

Can someone please point me in the right direction.

Thanks in advance. John

8 Answers 8

1

There are multiple ways to achieve this. One is to use the System.Net.FtpWebRequest as shown in this example: http://www.systemcentercentral.com/BlogDetails/tabid/143/IndexID/81125/Default.aspx

Or there are /n Software NetCmdlets you can use:

http://www.nsoftware.com/powershell/tutorials/FTP.aspx

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for the quick respone. I took a look at your first example, but the issue is that it assumes I know what I'll be downloading. As for the /n NetCmdlets, alas my company won't pay for them :-(
aah, So using wildcards is the only option! I will see if I have any other references.
1

In a batch I can quite simply use the ftp.exe and the mget command with wildcards??

You can do the same in Powershell if you want to.

For a more Powershell way, you can use the FTPWebRequest. See here: http://msdn.microsoft.com/en-us/library/ms229711.aspx. You can build on the example to download multiple files in a loop.

But bottomline is, you do not have to convert something you have in batch to Powershell. You can, if you want, but what you have in batch, especially when calling external programs, should work just as well.

1 Comment

I agree with what you're saying, but in this caase using the Win32 FTP.exe doesn't give me enough flexability; Which is kind of strange, considering PowerShell doesn't give me the functionality!?!
1

Another resource you might want to check: PowerShell FTP Client Module

http://gallery.technet.microsoft.com/scriptcenter/PowerShell-FTP-Client-db6fe0cb

Comments

0

Oddly enough there are no built in cmdlets to deal with FTP. I'm not sure why the PowerShell team made that decision but it means you'll have to rely on using .NET code, a third party script/module/snap-in or a Win32 program such as FTP.exe as others have already answered with.

Here's is an example of downloading multiple files (binary and text) using .NET code:

$files = "Firefox Setup 9.0.exe", "Firefox Setup 9.0.exe.asc"
$ftpFolder = 'ftp://ftp.mozilla.org/pub/firefox/releases/9.0/win32/en-US'
$outputFolder = (Resolve-Path "~\My Documents").Path

foreach ($file in $files) {
    try {
        $uri = $ftpFolder + '/' + $file
        $request = [Net.WebRequest]::Create($uri)
        $request.Method = [Net.WebRequestMethods+Ftp]::DownloadFile
        $responseStream = $request.GetResponse().GetResponseStream()

        $outFile = Join-Path $outputFolder -ChildPath $file
        $fs = New-Object System.IO.FileStream $outFile, "Create"

        [byte[]] $buffer = New-Object byte[] 4096

        do {
            $count = $responseStream.Read($buffer, 0, $buffer.Length)
            $fs.Write($buffer, 0, $count)
        } while ($count -gt 0)

    } catch {
        throw "Failed to download file '{0}/{1}'. The error was {2}." -f $ftpFolder, $file, $_
    } finally {
        if ($fs) { $fs.Flush(); $fs.Close() }
        if ($responseStream) { $responseStream.Close() }
    }
}

6 Comments

I think this would work, but I would need to create the $files list before I download as the file names change everyday. In VBscript I would have used something like "mget " & "IDY03101." & Year() & Month()& Day() & "*.axf" which would download all the files for that day.
@JohnE You want to use Get-Date cmdlet to format the file name. $file = 'IDY03101.{0}.axf' -f (Get-Date -Format yyyyddmm).
Thanks Andy, I guess the only thing I need to do now is find a good way to export the list of files to use for $files. Would @ravikanth example be a good way to do this?
@JohnE It's easy to get a FTP dir file listing and download every file or every file that matches so naming criteria.
@Andy how would you download every file matching the FTP dir listing?
|
0

@Jacob. You need ::ListDirectory method to make a list. After, you have to output it in a text file with the out-file command. After that, you import the list with the get-content command. So with a text file, you can make a collection of objects with a foreach loop (don't forget to skip the last line with the '-cne' condition). You include in this loop your download-ftp function with the parameter of your loop. Understood ? Not sure if my explanation is good.

So there's an example from one of my script :

$files = Get-FtpList $ftpSource $ftpDirectory $ftpLogin $ftpPassword | Out-File -Encoding UTF8 -FilePath list.txt

$list = Get-Content -Encoding UTF8 -Path list.txt

foreach ($entry in $list -cne "")
{
Get-FtpFile $ftpSource $ftpDirectory $entry $target $ftpLogin $ftpPassword
Start-Sleep -Milliseconds 10
}

Hope it works now for you.

PS:Get-FtpList and Get-FtpFile are custom functions.

Comments

0

This is what i did.As i needed to download a file based on a pattern i dynamically created a command file and then let ftp do the rest I used basic powershell commands. i did not need to download any additional components I first Check if the Requisite number of files exist. if they do i invoke the FTP the second time with an Mget. I run this from a windows 2008 Server connecting to a windows XP remote server

            function make_ftp_command_file($p_file_pattern,$mget_flag)
               {
               # This function dynamically prepares the FTP file
               # The file needs to be prepared daily because the pattern changes daily
               # Powershell default encoding is Unicode
               # Unicode command files are not compatible with FTP so we need to make sure we create an  ASCII File

               write-output "USER" | out-file -filepath C:\fc.txt -encoding ASCII
               write-output "ftpusername" | out-file -filepath C:\fc.txt -encoding ASCII -Append
               write-output "password" | out-file -filepath C:\fc.txt -encoding ASCII -Append
               write-output "ASCII" | out-file -filepath C:\fc.txt -encoding ASCII -Append
               If($mget_flag -eq "Y")
               {
                  write-output "prompt" | out-file -filepath C:\fc.txt -encoding ASCII -Append
                  write-output "mget $p_file_pattern" | out-file -filepath C:\fc.txt -encoding ASCII -Append
               }
               else
               {
                  write-output "ls $p_file_pattern" | out-file -filepath C:\fc.txt -encoding ASCII -Append
               }          

               write-output quit | out-file -filepath C:\fc.txt -encoding ASCII -Append

            }

            ###########################  Init Section ###############################
            $yesterday = (get-date).AddDays(-1)
            $yesterday_fmt = date $yesterday -format "yyyyMMdd"
            $file_pattern = "BRAE_GE_*" + $yesterday_fmt + "*.csv"
            $file_log = $yesterday_fmt + ".log"

            echo  $file_pattern
            echo  $file_log



            ############################## Main Section ############################
            # Change location to folder where the files need to be downloaded
            cd c:\remotefiles

            # Dynamically create the FTP Command to get a list of files from the Remote Servers
            echo "Call function that creates a FTP Command "
            make_ftp_command_file $file_pattern N


            #echo "Connect to remote site via FTP"
            # Connect to Remote Server and get file listing
            ftp -n -v -s:C:\Clover\scripts\fc.txt 10.129.120.31 > C:\logs\$file_log

            $matches=select-string -pattern "BRAE_GE_[A-Z][A-Z]*" C:\logs\$file_log

            # Check if the required number of Files available for download
            if ($matches.count -eq 36)
            {
                # Create the ftp command file
                    # this time the command file has an mget rather than an ls
                make_ftp_command_file $file_pattern Y
                    # Change directory if not done so
                cd c:\remotefiles
                    # Invoke Ftp with newly created command file
                ftp -n -v -s:C:\Clover\scripts\fc.txt 10.129.120.31 > C:\logs\$file_log 
            }
            else
            {
                echo "Full set of Files not available"
            }

Comments

0

It's not Powershell specific. But I've tried many other solutions and so far

The http://ncftp.com/ client works the best. It comes with ncftpls.exe for listing remote files and ncftpget.exe for getting files. Use them with Start-Process -Wait

Comments

0

A file list can be constructed in a variable, and used with a regular FTP command....

$FileList="file1_$cycledate.csv
file2_$cycledate.csv
file3_$cycledate.csv
file4_$cycledate.csv"

"open $FTPServer
    user $FTPUser $FTPPassword
ascii
cd report
" +
($filelist.split(' ') | %{ "mget $_" }) | ftp -i -n

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.