M12i.

学術書・マンガ・アニメ・映画の消費活動とプログラミングについて

コマンドプロンプトからFTP転送を行うスクリプトをつくってみた

WindowsコマンドプロンプトFTP転送処理をするにはどうしたらよいのだろう?と思ってしらべてみたら「いろいろ面倒だ」ということがわかりました。あれこれ試しながらつくったスクリプトは以下のとおり:

ftpput.bat

@echo off
setlocal

rem FTPPUTコマンドのデフォルトの終了コードは0
set FTPPUT_EXITCODE=0

rem 日時と乱数を組み合わせ一時ファイルの接尾辞を作成
set /A HASH1=%random%+100000
set HASH1=%HASH1:~1,5%
set /A HASH2=%random%+100000
set HASH2=%HASH2:~1,5%
set SUFFIX=%date:~-10,4%%date:~-5,2%%date:~-2,2%%time:~0,2%%time:~3,2%%time:~6,2%
set SUFFIX=%HASH1%_%HASH2%_%SUFFIX: =0%
set USAGE=FTPPUT.BAT ホスト名 ユーザ名 パスワード ローカルパス リモートパス

rem FTPコマンドの実行に関わる変数を設定
rem ftpput.bat <host> <user> <password> <local-path> <remote-path>
set FTP_HOST=%1
set FTP_USER=%2
set FTP_PASSWORD=%3
set FTP_LOCAL_PATH=%4
set FTP_REMOTE_PATH=%5
set FTP_SCRIPT=ftpput_%SUFFIX%.tmp
set FTP_SCRIPT_LOG=ftpput_%SUFFIX%.tmp.log

rem コマンドライン引数のチェック
if "%FTP_HOST%"=="" (
	echo %USAGE%
	exit /B 1
)
if "%FTP_USER%"=="" (
	echo %USAGE%
	echo 第2引数「ユーザ名」が未設定
	exit /B 1
)
if "%FTP_PASSWORD%"=="" (
	echo %USAGE%
	echo 第3引数「パスワード」が未設定
	exit /B 1
)
if "%FTP_LOCAL_PATH%"=="" (
	echo %USAGE%
	echo 第4引数「ローカルパス」が未設定
	exit /B 1
)
if not exist %FTP_LOCAL_PATH% (
	echo 第4引数「ローカルパス」のファイルが存在しない
	exit /B 1
)

if "%FTP_REMOTE_PATH%"=="" (
	echo %USAGE%
	echo 第5引数「リモートパス」が未設定
	exit /B 1
)

rem FTPコマンドに渡すためのスクリプトを作成
echo open %FTP_HOST%> %FTP_SCRIPT%
echo %FTP_USER%>> %FTP_SCRIPT%
echo %FTP_PASSWORD%>> %FTP_SCRIPT%
echo binary>> %FTP_SCRIPT%
echo put %FTP_LOCAL_PATH% %FTP_REMOTE_PATH%>> %FTP_SCRIPT%
echo quit>> %FTP_SCRIPT%

rem FTPコマンドを実行し結果を専用ログファイルに出力
ftp -s:%FTP_SCRIPT% > %FTP_SCRIPT_LOG%

rem ログファイルを解析して転送成否を確認
echo "ftp -s:%FTP_SCRIPT% > %FTP_SCRIPT_LOG%"
for /F "delims=" %%i in (%FTP_SCRIPT_LOG%) do (
	echo " | %%i"
	rem 転送失敗を示す文字列があれば終了コードを1に設定
	for /F "delims=" %%j in ('findstr /R /C:"^[4-5][0-9][0-9]" %FTP_SCRIPT_LOG%') do (
		set FTPPUT_EXITCODE=1
	)
)

rem 一時ファイルを削除
del %FTP_SCRIPT%
del %FTP_SCRIPT_LOG%

echo exit /B %FTPPUT_EXITCODE%
exit /B %FTPPUT_EXITCODE% 

主な制約として、単一ファイルのアップロードにしか対応していません。匿名ログインはできません。また、ファイル転送成否の判断には400もしくは500番台のステータスコードのメッセージの有無を使用しており、ファイル転送成功時のメッセージが異なる場合には当然判定がおかしくなります。