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

CGIテクニック集トップへ





概要

これはCGIではありません。コマンドプロンプトから実行するスクリプトです。 複数の場所で使われている同一CGI等をバージョンアップなどで更新したいときにワンコマンドで全てのディレクトリにアップロードすることができます。

コマンドの使い方

 putall.pl <filename> <username> <password>

スクリプト名をputall.plとします。アップロードしたいファイルがあるディレクトリでputall.plを実行します。第一引数としてアップロードするファイル名、第二引数としてusername、第三引数としてpasswordを入れます。アップロードするファイル名にパスは含まないようにしてください。

必用な処理

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

サンプルコード

 use Net::FTP;
 
 my %db = (
          'site' => "ftp.yoursite.com",
          'root' => "subdir/cgi-bin",
          'subdir' => [qw(
                         dir1
                         dir2
                         dir3
                         dir4
                         dir5
                         )],
          );
 
 die "Usage: $0 <filename> <username> <password>\n" 
     if ($#ARGV < 2);
 
 my $ftpsite = $db{site};
 
 my $filename = $ARGV[0];
 my $username = $ARGV[1];
 my $password = $ARGV[2];
 
 my $ftp = Net::FTP->new("$ftpsite") or 
     die "Cannot connect to $ftpsite : $@";
 $ftp->login("$username", "$password") or 
     die "Cannot login : ", $ftp->message;
 
 foreach my $dir (@{$db{subdir}}){
     print "$filename -> $db{root}/$dir\n";
     $ftp->put("$filename","$db{root}/$dir/$filename") or 
        die "put failed : ", $ftp->message;
     print $ftp->message;
 }
 
 $ftp->quit();

コードの解説

 use Net::FTP;

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

 my %db = (
          'site' => "ftp.yoursite.com",
          'root' => "subdir/cgi-bin",
          'subdir' => [qw(
                         dir1
                         dir2
                         dir3
                         dir4
                         dir5
                         )],
          );

ログインするFTPサイト、リモートホストでのホームディレクトリからみた共通のディレクトリ、その下のファイルをアップロードする各サブディレクトリを指定します。上の設定では、 ftp.yoursite.comにログインし、そのホームディレクトリ以下の

   subdir/cgi-bin/dir1
   subdir/cgi-bin/dir2
   subdir/cgi-bin/dir3
   subdir/cgi-bin/dir4
   subdir/cgi-bin/dir5

の各ディレクトリにファイルをアップロードします。

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

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

 my $ftpsite = $db{site};

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

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

引数からそれぞれアップロードするファイル名を$filename, 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 $dir (@{$db{subdir}}){
     print "$filename -> $db{root}/$dir\n";
     $ftp->put("$filename","$db{root}/$dir/$filename") or 
        die "put failed : ", $ftp->message;
     print $ftp->message;
 }

サブディレクトリが入った配列を一つずつ読み込み、$filenameをそのディレクトリにアップロードします。これはサブディレクトリの数だけ繰り返されます。この例ではdir1からdir5まで5回繰り返されます。一つのアップロードごとに$ftp->messageでFTPのメッセージを表示します。全てのアップロードが終わるとループを終了します。

 $ftp->quit();

FTPをquitします。

アップロードするファイルがCGIでパーミッションを0755に自動で設定したい場合は、

 foreach my $dir (@{$db{subdir}}){
     print "$filename -> $db{root}/$dir\n";
     $ftp->put("$filename","$db{root}/$dir/$filename") or 
        die "put failed : ", $ftp->message;
     print $ftp->message;
     $ftp->site("chmod 755 $db{root}/$dir/$filename") or 
        die "site failed : ", $ftp->message;
     print $ftp->message;
 }

のように

 $ftp->site("chmod 755 $db{root}/$dir/$filename") or 
      die "site failed : ", $ftp->message;

をputの後に実行することでできます。

関連するCGIテクニック

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