29

I am using cURL to try to download all files in a certain directory.

here's what my list of files looks like:

enter image description here

I have tried to do in bash script: iiumlabs.[].csv.pgp and iiumlabs* and I guess curl is not big on wildcards.

curl -u login:pass ftp.myftpsite.com/iiumlabs* -O

question: how do i download this directory of files using cURL?

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
Alex Gordon
  • 57,446
  • 287
  • 670
  • 1,062
  • Do you want to download *the whole* directory (and wildcard is not really relevant here) or just some files in it matching the wildcard? – Michał Górny Aug 02 '12 at 18:47
  • @MichałGórny either one would be amazing! – Alex Gordon Aug 02 '12 at 18:48
  • do you have a simple solution :) ??? – Alex Gordon Aug 02 '12 at 18:54
  • Are you bound to `curl`? To be honest, it's one of the most hard-to-use tools I've ever seen. What is your platform? Because in the post you mention bash, and in the answer comments you mentioned .bat files... Also, how is `sftp` relevant? And does your example actually use FTP? Because there's no `ftp://` there so I'm pretty sure curl used HTTP... – Michał Górny Aug 02 '12 at 18:55
  • @MichałGórny no im not bound to curl. i need a tool that can access sFTP and FTP and download files. i am running on windows. i am at the same time looking for an app that will decrypt PGP after the files are downloaded – Alex Gordon Aug 02 '12 at 19:01
  • I'll answer you in a short while. – Michał Górny Aug 02 '12 at 19:07

7 Answers7

63

If you're not bound to curl, you might want to use wget in recursive mode but restricting it to one level of recursion, try the following;

wget --no-verbose --no-parent --recursive --level=1 \
--no-directories --user=login --password=pass ftp://ftp.myftpsite.com/
  • --no-parent : Do not ever ascend to the parent directory when retrieving recursively.
  • --level=depth : Specify recursion maximum depth level depth. The default maximum depth is five layers.
  • --no-directories : Do not create a hierarchy of directories when retrieving recursively.
  • --delete-after : can be added if you need to delete files after downloading.
  • --no-host-directories : to download right in '.' current folder, not create directory named by domain.
  • --no-clobber : skip downloads that would download to existing files
  • --continue : Continue getting a partially-downloaded file for more stability
  • combine with cd : to define the destination directory

So this sample can look like following:

cd /home/destination/folder \
&& wget --no-verbose --no-parent --recursive --level=1 \
--no-directories --no-host-directories \
--no-clobber --continue \ 
--user=login --password=pass ftp://ftp.myftpsite.com/
kkeller
  • 3,047
  • 3
  • 15
  • 11
  • thank you very much!! do you know if it is possible to do the same with sFTP (ftp over ssh) ?? – Alex Gordon Aug 02 '12 at 21:08
  • sftp is only an addition to ssh. When ssh is enabled you should be able to use scp as well and doing it with scp should be much easier: scp user@ftp.myftpsite.com/mydirectory/\* . You'll need to exchange SSH keys first to make that passwordless. And I'm not quite sure about the quoting syntax of * if you run this from windows. – kkeller Aug 02 '12 at 21:17
  • The question is how to do this using curl, not wget. – vahotm Aug 11 '20 at 10:00
  • 1
    In addition to that, the following parameters could be added for more stability: -nc, --no-clobber: skip downloads that would download to existing files and also --continue – Thales Valias Jan 25 '21 at 15:44
  • `--delete-after` can be added if you need to delete files after downloading. – Eugene Kaurov Mar 15 '23 at 11:02
  • `--no-host-directories` to download right in '.' current folder, not create directory named by domain. – Eugene Kaurov Mar 15 '23 at 11:04
  • For special characters in password, use quotas `--user="login" --password="pass"` – Eugene Kaurov Mar 15 '23 at 11:37
14

OK, considering that you are using Windows, the most simple way to do that is to use the standard ftp tool bundled with it. I base the following solution on Windows XP, hoping it'll work as well (or with minor modifications) on other versions.

First of all, you need to create a batch (script) file for the ftp program, containing instructions for it. Name it as you want, and put into it:

curl -u login:pass ftp.myftpsite.com/iiumlabs* -O

open ftp.myftpsite.com
login
pass
mget *
quit

The first line opens a connection to the ftp server at ftp.myftpsite.com. The two following lines specify the login, and the password which ftp will ask for (replace login and pass with just the login and password, without any keywords). Then, you use mget * to get all files. Instead of the *, you can use any wildcard. Finally, you use quit to close the ftp program without interactive prompt.

If you needed to enter some directory first, add a cd command before mget. It should be pretty straightforward.

Finally, write that file and run ftp like this:

ftp -i -s:yourscript

where -i disables interactivity (asking before downloading files), and -s specifies path to the script you created.


Sadly, file transfer over SSH is not natively supported in Windows. But for that case, you'd probably want to use PuTTy tools anyway. The one of particular interest for this case would be pscp which is practically the PuTTy counter-part of the openssh scp command.

The syntax is similar to copy command, and it supports wildcards:

pscp -batch login@mysshsite.com:iiumlabs* .

If you authenticate using a key file, you should pass it using -i path-to-key-file. If you use password, -pw pass. It can also reuse sessions saved using PuTTy, using the load -load your-session-name argument.

Uli Köhler
  • 13,012
  • 16
  • 70
  • 120
Michał Górny
  • 18,713
  • 5
  • 53
  • 76
  • how did you do this so fast? did you know how to do this already or did you check documentation? – Alex Gordon Aug 02 '12 at 19:28
  • Well, I knew it should have something like this; I just needed a while to find how to get to the help of it, and how to make it working. It wasn't as easy as such things are on Linux... – Michał Górny Aug 02 '12 at 19:49
  • does this handle sFTP? i have a key file that needs to be used in order to gain access to a certain ftp – Alex Gordon Aug 02 '12 at 19:56
  • Sorry but I have no idea. Also, do you mean sFTP as in ftp+ssl or file transfer over SSH? – Michał Górny Aug 02 '12 at 20:47
  • Well, SSH on Windows is usually best achieved using [PuTTy](http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html). I'm pretty sure `pscp` work just fine (it's practically a `scp` counter-part). I'll add the simple way of using it to the answer. – Michał Górny Aug 03 '12 at 07:12
  • Just for the sake of it (and someone might have use for the knowledge) SFTP = ftp over ssh FTPS = ftp+ssl – Griffin Jun 18 '18 at 21:19
  • If you need to use key files you use the parameter -i [keyfile] . But in case you have a "normal" key you first have to convert it using PuttyGen.exe as described on https://devops.profitbricks.com/tutorials/use-ssh-keys-with-putty-on-windows/ – Griffin Jun 18 '18 at 21:23
11

What about something like this:

for /f %%f in ('curl -s -l -u user:pass ftp://ftp.myftpsite.com/') do curl -O -u user:pass ftp://ftp.myftpsite.com/%%f
Robi
  • 111
  • 1
  • 2
  • 1
    I guess you were late to this question but this answer solved my problem for me so thanks a lot! – Adamon Dec 06 '18 at 11:11
6

You can use script like this for mac:

for f in $(curl -s -l -u user:pass ftp://your_ftp_server_ip/folder/) 
 do curl -O -u user:pass ftp://your_ftp_server_ip/folder/$f 
done
M.Selman SEZGİN
  • 183
  • 3
  • 11
1

Oh, I have just the thing you need!

$host = "ftp://example.com/dir/";
$savePath = "downloadedFiles";
if($check = isFtpUp($host)){

    echo $ip." -is alive<br />";

    $check = trim($check);
    $files = explode("\n",$check);

    foreach($files as $n=>$file){
        $file = trim($file);
        if($file !== "." || $file !== ".."){
            if(!saveFtpFile($file, $host.$file, $savePath)){
                // downloading failed. possible reason: $file is a folder name.
                // echo "Error downloading file.<br />";
            }else{
                echo "File: ".$file." - saved!<br />";
            }
        }else{
            // do nothing
        }
    }
}else{
    echo $ip." - is down.<br />";
}

and functions isFtpUp and saveFtpFile are as follows:

function isFtpUp($host){
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, $host);
curl_setopt($ch, CURLOPT_USERPWD, "anonymous:your@email.com");
curl_setopt($ch, CURLOPT_FTPLISTONLY, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 3);

$result = curl_exec($ch);

return $result;

}

function saveFtpFile( $targetFile = null, $sourceFile = null, $savePath){

// function settings
set_time_limit(60);
$timeout = 60;
$ftpuser = "anonymous";
$ftppassword = "your@email.com";
$savePath = "downloadedFiles"; // should exist!
$curl = curl_init();
$file = @fopen ($savePath.'/'.$targetFile, 'w');

if(!$file){
    return false;
}

curl_setopt($curl, CURLOPT_URL, $sourceFile);
curl_setopt($curl, CURLOPT_USERPWD, $ftpuser.':'.$ftppassword);

// curl settings

// curl_setopt($curl, CURLOPT_FAILONERROR, 1);
// curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_TIMEOUT, $timeout);
curl_setopt($curl, CURLOPT_FILE, $file);

$result = curl_exec($curl);


if(!$result){
    return false;
}

curl_close($curl);
fclose($file);

return $result;
}

EDIT:

it's a php script. save it as a .php file, put it on your webserver, change $ip to address(need not be ip) of ftp server you want to download files from, create a directory named downloadedFiles on the same directory as this file.

Prasanth
  • 5,230
  • 2
  • 29
  • 61
  • wow. looks amazing. can you please help me get started on how to run this? just put it in a txt file, rename to BAT and run ?? – Alex Gordon Aug 02 '12 at 18:24
  • thank you very much for the explanation. is it possible to run this without a webserver? – Alex Gordon Aug 02 '12 at 18:33
  • 1
    Umm, no! At the least, you'd have to install standalone php with cURL. – Prasanth Aug 02 '12 at 18:35
  • Ah, I personally use WAMP server. Check out [WampServer](http://wampserver.com/en/) and download any version and run the script or try XAMPP. – Prasanth Aug 02 '12 at 18:44
  • thanks so much. i am definitely going to try this solution, but in the mean time still looking for something i can run off my windows machine in a BAT file – Alex Gordon Aug 02 '12 at 18:49
  • Couldn't you invent a more complex and heavier solution for a very simple problem? – Michał Górny Aug 02 '12 at 18:50
  • 1
    Oh, I just pasted something I had already written. When I wrote this, I wanted it specifically in php, curl. So, at that time, it was the perfect solution for me. – Prasanth Aug 02 '12 at 18:54
  • can you help me something more ? if internet connection is interrupted during file downloading , then after i not want download file from scratch but i wanl resume. – Ajay Bhayani May 12 '17 at 05:46
1

Here is how I did to download quickly with cURL (I'm not sure how many files it can download though) :

setlocal EnableDelayedExpansion

cd where\to\download

set STR=
for /f "skip=2 delims=" %%F in ('P:\curl -l -u user:password ftp://ftp.example.com/directory/anotherone/') do set STR=-O "ftp://ftp.example.com/directory/anotherone/%%F" !STR!
path\to\curl.exe -v -u user:password !STR!

Why skip=2 ? To get ride of . and ..

Why delims= ? To support names with spaces

kiwixz
  • 1,380
  • 15
  • 23
0

If you're not bound to curl, you might want to use lftp , try the following:

lftp ftp://ftp.some.domain.com -u login@some.domain.com,'password' -e 'set ftp:ssl-allow no; mirror --Remove-source-files --verbose /remote/directory /home/destination/folder; bye'

Where

  • -u username
  • ,'password' : put your password rather in quotas
  • --Remove-source-files : deete remove files after you downloaded them
  • --verbose : good to see info but feel free to delete on production
  • set ftp:ssl-allow no; : only in case if you do not need to check certificate (not ssl)
Eugene Kaurov
  • 2,356
  • 28
  • 39