cmd2ftp は、ローカルホスト上で実行するコマンドの出力を、ftp を経由して、直接リモートホスト上のファイルに出力するための ftp クライアントのラッパーである。
ローカルホスト上で、シェルで処理した出力を、リモートホストに書き出したい、という時に、普通だったら、 ssh とパイプを使うところだが、ssh は ftp に較べると、問題外に性能が悪く、ここは ftp を使いたい所だ。
ところが、昔ながらの ftp クライアントは、この機能、すなわちローカルコマンド出力を直接 put する機能があるが、対話的に操作をする気になれないようなインタフェースになっている。 そこで、この操作性を改善し、ssh の手軽さで、ftp の性能を享受すべくこのラッパを書いた。
※ 後日談だが、公開後に、cmdwftp の機能は ncftp に同梱されている ncftpput で可能である、という指摘を頂戴した。この議論に関しては、凡例を参照されたい。
% tar xvjf cmd2ftp-0.01.tar.bz2 % cd cmd2ftp-0.XXX % make install
正しくインストールされると man cmd2ftp もしくは cmd2ftp -man でマニュアルが表示される。
% cat DersuUzala_1974.md{f,0,1,2} | ssh video "cat > /tmp/image.iso"しかし ssh のファイル転送は重い。無駄だと思うだろう。こんなもので満足していては駄目だ。
これを使うと、↓のようになる。
% ftp -i -n video << END heredoc> user Id Pass heredoc> cd /tmp heredoc> put |"cat DersuUzala_1974.md{f,0,1,2}" "image.iso" heredoc> quit heredoc> ENDスクリプト中に書くのならいざ知らず、今時対話的にこんな操作をする人間なんていないだろう。やってられないよな。
しかし、だ、ファイル転送性能は、ssh に較べて ftp の方が圧倒的に高いんだ。これは適当なラッパをデッチ上げるしかない。
% cmd2ftp -h video -u Id,Pass -c "'cat DersuUzala_1974.md{f,0,1,2}' -d /tmp -o image.iso
以下は、高橋 "masaka" 正和 さんのコメントに依る。
ncftp に同梱されている ncftpput (-c オプション) を使うと、出力をパイプを通してリモートホストに put できる。
$ cat DersuUzala_1974.md{f,0,1,2} | ncftpput -u Id -p Pass -c video /tmp/image.iso
とか思ったんですが、ちょっと試した範囲では、ftp でやるのにくらべて低速でした。という訳で cmd2ftp を書いてやっぱりよかった。
本項は 尾山@渋谷さんのコメントによる。
netcat をバッチ的に使う場合はコツがいる
% ssh video 'nc -l -p 2000 > /tmp/image.iso ' & ; \ sleep 1 ; cat DersuUzala_1974.md{f,0,1,2} | nc -q 0 video 2000
更にこいつは、ssh 同様に、リモート側で出力をパイプに繋げて更に処理をすることができる。 下は、リモート側でパイプラインを繋げた例
% ssh video 'nc -l -p 2000 | wc -l > /tmp/foo.txt ' & ; \ sleep 1 ; cat test.txt | nc -q 0 video 2000これだと、ftp のように、平文でパスワードが流れたりしないし、ssh より軽い。 しかし、環境によって sleep とか nc -q に与える待ち時間を調整する必要がある。 使い手を選ぶ道具であると思う。
シェル変数も、制御構造も、パイプやリダイレクトも使うことができるし セミコロンで複数コマンドを列挙することもできる。
途中に改行があると、そこでコマンドはシェルに渡されてしまって、次に出現する空白文字で区切られたトークンが、出力ファイル名になる。
cmd2ftp では、コマンド中の改行を許容する。つまり次のように、書くこともできる。
% cmd2ftp -h video -u Id,Pass --cmd 'for f in * quote> do ls -l $f quote> done ' -d /tmp -o result.txt
こちら に書いた。