FTPでサーバー上の複数のディレクトリ(フォルダ)から対応するローカルディレクトリに一度でダウンロードする方法

CGIテクニック集トップへ





概要

これはCGIではありません。コマンドプロンプトから実行するスクリプトです。 サーバー上で更新された複数のデータをバックアップ等のためにローカルマシンに一度でダウンロードしたい時に役に立ちます。

コマンドの使い方

 getall.pl <username> <password>

スクリプト名をgetall.plとします。第一引数としてusername、第二引数としてpasswordを入れます。

必用な処理

  1. Net::FTPを読み込む
  2. ダウンロードしたいファイル、ディレクトリ情報を設定する
  3. 引数から必用な情報を読み込み変数に入れる
  4. FTPに接続しオブジェクトを作成
  5. FTPサイトにログインする
  6. それぞれのファイルに対しgetコマンドを実行しダウンロードする
  7. 全ディレクトリのアップロードが終了するとquitする

サンプルコード

 use Net::FTP;
 
 my %db = (
          'site' => "ftp.yoursite.com",
          'root' => "myhome/html",
          'local' => 'd:\www\home\html',
          'items' => [qw(
                         index.html
                         bbs/datafile.dat
                         mydata.log
                         )],
       );
 
 die "Usage: $0 <username> <password>\n" if ($#ARGV < 2);
 
 my $ftpsite = $db{site};
 my $username = $ARGV[0];
 my $password = $ARGV[1];
 
 my $ftp = Net::FTP->new("$ftpsite") 
        or die "Cannot connect to $ftpsite : $@";
 $ftp->login("$username", "$password") 
        or die "Cannot login : ", $ftp->message;
 
 foreach my $file (@{$db{items}}){
     $ftp->get("$db{root}/$file","$db{local}/$file") 
        or die "get failed : ", $ftp->message;
     print $ftp->message;
 }
 
 $ftp->quit();

コードの解説

 use Net::FTP;

PerlのPackage, Net::FTPを読み込みます。

 my %db = (
          'site' => "ftp.yoursite.com",
          'root' => "myhome/html",
          'local' => 'd:\www\home\html',
          'items' => [qw(
                         index.html
                         bbs/datafile.dat
                         mydata.log
                         )],
       );

ログインするFTPサイト、リモートホストでのホームディレクトリからみた全ファイル共通のディレクトリ、ローカルマシンでの全ファイル共通ディレクトリ、その下に来るダウンロードする全ファイルを指定します。上の設定では、 ftp.yoursite.comにログインし、そのFTPサーバーからローカルマシンに

 myhome/html/index.html        --->   d:\www\home\html\index.html
 myhome/html/bbs/datafile.dat  --->   d:\www\home\html\bbs\datafile.dat
 myhome/html/mydata.log        --->   d:\www\home\html\mydata.log

のようにファイルをダウンロードします。ローカルマシン側では/と\が混ざっていても正常に動くようです。

 die "Usage: $0 <username> <password>\n" if ($#ARGV < 2);

コマンドを実行する際、引数が正しく与えられていない場合に使い方を表示し、スクリプトを終了します。

 my $ftpsite = $db{site};

ログインするFTPサーバー名を$ftpsiteに入れます。

 my $username = $ARGV[0];
 my $password = $ARGV[1];

引数からFTPのユーザー名を$username, そのパスワードを$passwordに引き渡します。

 my $ftp = Net::FTP->new("$ftpsite") 
        or die "Cannot connect to $ftpsite : $@";

FTPサイトに接続します。この時点ではまだログインしていません。

 $ftp->login("$username", "$password") 
        or die "Cannot login : ", $ftp->message;

ここでユーザー名とパスワードを渡し、ログインします。失敗した場合にはメッセージと共に終了します。

 foreach my $file (@{$db{items}}){
     $ftp->get("$db{root}/$file","$db{local}/$file") 
        or die "get failed : ", $ftp->message;
     print $ftp->message;
 }

ダウンロードするファイルが入った配列を一つずつ読み込み、$fileを一つずつダウンロードします。これは設定されているファイルの数だけ繰り返されます。この例では3回繰り返されます。一つのダウンロードごとに$ftp->messageでFTPのメッセージを表示します。全てのダウンロードが終わるとループを終了します。前述したようにローカルマシン側ではディレクトリのセパレータとして\と/が混ざっても正常に動くようです。

 $ftp->quit();

FTPをquitします。

関連するCGIテクニック

FTPで一つのファイルを複数のディレクトリ(フォルダ)に一度でアップロードする方法