†REXXのどろぬま†
作成開始日 2010.03.11
最終更新日
【注意】2025年現在、OS/2標準のftpでftpサーバにアクセスするのは困難になって来ている。代わりにNcFtp-3.2.5を使用することを推奨する。NcFtpならば、REXX FTP APIの代りになるプログラム(ncftpput, ncftpget, ncftpls等)が用意されている。
[アシスタンス・センター|情報]の中にREXX FTP APIの解説書があるので、それを読めば使い方は判る。以下、基本的な処理の流れを簡単に。
/*** REXXのFTP APIを読み込む***/
rc = RxFuncAdd("FtpLoadFuncs","rxFtp","FtpLoadFuncs")
rc = FtpLoadFuncs()
/* ftpサーバに接続(ホスト名、ユーザー名、パスワードの順)*/
rc = FtpSetUser('ftp.xxxx.yyyy.zzz.ne.jp','my-name','xxxxxxx');
/* 転送モードをバイナリに設定(テキストでもこの方が良い)*/
rc = FtpSetBinary('Binary');
/* サーバ上のファイル一覧、日付情報などの取得 */
/* 例)サーバ上の「/html/os2」ディレクトリにある「*.htm」ファイルの一覧 */
rc = FtpDir('/html/os2/*.htm','file.')
do n=1 to file.0
say file.n
end
/* ftpサーバにディレクトリを作成する */
/* 例)サーバ上の「/html」の中に「/video」というディレクトリを作成する */
rc = FtpMkDir('/html/video')
/* ファイルをサーバにアップする*/
/* 例)ローカルにある「index.htm」をサーバ上の「/html/video/」にコピーする */
/* 注意)コピー先はディレクトリ名だけでなく、ファイル名必須 */
rc = FtpPut('index.htm', '/html/video/index.htm');
/* ログオフ */
rc = FtpLogoff();
/* エラーの確認(各コマンドの実行後) */
if rc=-1 then say '*** エラー発生' FTPERRNO
| 種類 | 形式 | 用例 |
| 1年以内のタイムスタンプ | 月(英字3文字) 日 時:分(24h表示) | Mar 11 20:45 |
| 1年以前のタイムスタンプ | 月(英字3文字) 日 年(4桁) | Jul 7 2017 |
この形式ではタイムスタンプの新旧比較が非常に面倒。具体的な処理方法は後述のサンプル2を参照。
なお、ftpサーバ上のファイルのタイムスタンプは、元ファイルの日付ではなく、アップロードの日付となる。元ファイルの更新日付が必要な場合は、別の方法で管理するしかない。アップロード元が1つだけなら、ローカルとリモートのファイル日付の比較だけで新旧の判別は可能だが、厄介なのは、複数の場所から更新処理をする場合。以前は、元のタイムスタンプの一覧ファイルを作成していた。個人的には、仕事場を一つに絞ったので、その必要はなくなったけれど…
/*********************************************************************/
/* ftp uploader */
/*********************************************************************/
Call RxFuncAdd 'SysLoadFuncs', 'RexxUtil', 'SysLoadFuncs'
Call SysLoadFuncs
rc = RxFuncAdd("FtpLoadFuncs","rxFtp","FtpLoadFuncs")
rc = FtpLoadFuncs()
mask=arg(1) /* ワイルドカード指定可能 */
/* サーバ名、ユーザー名、パスワードを指定 */
rc = FtpSetUser('ftp.xxxx.yyyy.zzz.ne.jp','my-name','xxxxxxx');
if rc=-1 then say '*** エラー' ftperrno
rc = FtpSetBinary("Binary");
rc=sysfiletree(mask,'f.',FO)
do n=1 to f.0
/* ローカルファイル名からリモートファイル名を作成する */
/* ローカルとリモートのディレクトリ構造が一致していることが前提 */
/* たとえば、ローカル=d:\myhp\html\book\、リモート=/html/book/ */
remoteFname=translate(f.n,'/','\')
remoteFname=substr(remoteFname,9) /* ここは各自の環境に合わせて変更 */
/* ftpサーバ側に当該ディレクトリがあるか確認し、なければ作成する */
remoteDir=FileSpec('P',remoteFname)
rc = FtpDir(remoteDir, 'd.');
if d.0=0 then
do
say '*** MAKE DIRECTORY :' remoteDir
say
rc=FtpMkDir(remoteDir)
if rc=-1 then say '*** エラー' ftperrno
end
/* ファイルをアップロードする */
say remoteFname
rc = FtpPut(f.n, remoteFname);
if rc=-1 then say '*** エラー' ftperrno
end
rc = FtpLogoff();
EXIT
/*********************************************************************/
/* ftp update uploader 2018.03.11-2021.01.09 (c) suikodow */
/* 更新専用:サーバ上に同名ファイルがない場合は、日付に拘らずアップしない*/
/* 機能追加:/n オプションで新規ファイルをアップロード(2020.01.09) */
/* バグ修正:年またぎで1年以内の場合の日付形式の変換のバグ(2021.01.09) */
/*********************************************************************/
Call RxFuncAdd 'SysLoadFuncs', 'RexxUtil', 'SysLoadFuncs'
Call SysLoadFuncs
Call RxFuncAdd 'FtpLoadFuncs','rxFtp','FtpLoadFuncs'
Call FtpLoadFuncs
NUMERIC DIGITS 14 /* 有効桁数14桁:日時比較用*/
SAY '---------------------------------------------------------'
SAY 'fud -- ftp update uploader ver.0.1 2018.03.11 suikodow'
SAY '---------------------------------------------------------'
opt=arg(1)
if opt='/n' then flgNew=1; else flgNew=0
y0=left(date('S'),4) /* 今年の年 例)2021 */
d0=substr(date('S'),5,4) /* 今日の月日 例) 0109 */
/* ローカル&リモートのディレクトリを設定 */
curdir=directory();
remdir=substr(translate(curdir,'/','\'),9)
/* ローカルファイルの一覧と日時情報の取得 */
rc=sysfiletree(curdir'\*.*',lf.,'FT')
do n=1 to lf.0
parse var lf.n yy'/'mm'/'dd'/'hh'/'mn dmy dmy fname
dt=20||yy||mm||dd||hh||mn
lf.n=dt' 'filespec('N',fname)
end
/* リモートファイルの一覧と日付情報の取得 */
rc=FtpSetUser('ftp.xxx.yyy.zzz.com','myuserid','mypassword');
if rc=-1 then say '*** エラー' ftperrno
rc=FtpSetBinary('Binary');
rc=FtpDir(remdir,rf.)
do n=1 to rf.0
/* xxは「年(例 2018)」か「時分(例 18:32)」 */
parse var rf.n dmy dmy dmy dmy dmy mm dd xx fname
/* 月を英字表記から数字表記に変換 */
mm=wordpos(mm,'Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec')
mm=right('0'||mm,2)
dd=right('0'||dd,2)
d1=mm||dd /* リモートの日付(年なし) 例) 1205 / 後で使用する */
/* 時分か年かを判別して処理 */
if pos(':',xx)>0 then
Do
parse var xx hh':'mn
hh=right('0'||hh,2)
mn=right('0'||mn,2)
if d1>d0 then yy=y0-1; else yy=y0 /* 今日から1年以上前か否か */
End
Else do
hh=23
mn=59
yy=xx
End
rf.n=yy||mm||dd||hh||mn fname
end
/* 存否確認と新旧比較をして更新分をアップロード */
Do n=1 to lf.0
parse var lf.n ldt lname
Do m=1 to rf.0
parse var rf.m rdt rname
/* if (lname=rname) then say rname 'local='ldt 'remote='rdt 'd='ldt-rdt */
if (lname=rname)&(ldt>rdt) then
Do
say lname '( update :' dtform(rdt) '-->' dtform(ldt) ')'
rc=FtpPut(lname, remdir'/'rname)
if rc=-1 then say '*** エラー' ftperrno
End
End
End
/* 新規ファイルのアップロード(オプション) */
if flgNew=1 then
Do
Do n=1 to lf.0
flgSame=0
parse var lf.n ldt lname
Do m=1 to rf.0
parse var rf.m rdt rname
if lname=rname then flgSame=1
End
if flgSame=0 then
Do
say lname '( newfile :' dtform(ldt) ')'
rc=FtpPut(lname, remdir'/'lname)
if rc=-1 then say '*** エラー' ftperrno
End
End
End
rc=FtpLogoff();
exit
/*-------------------------------------------------------------------*/
dtform : Procedure
dt=arg(1)
yy=left(dt,4)
mm=substr(dt,5,2)
dd=substr(dt,7,2)
hh=substr(dt,9,2)
mn=substr(dt,11,2)
return yy'/'mm'/'dd'@'hh':'mn