Programmer's Note

コード読み書きの備忘録。

bundleプログラム改

'The Unix Programming Environment'の第3章の「USING THE SHELL」で bundle というツールが紹介されている。

これは以下のような小さなshellスクリプトのプログラムだ。 (作ったのはAlan Hewett, James Gosling.)

#bundle: group files into distribution package

echo '# To unbundle, sh this file'
for i
do
    echo "echo $i 1>&2"
    echo "cat >$i <<'End of $i'"
    cat $i
    echo "End of $i"
done

これで何をしているかというと、

$ bundle *

とすると、

  • カレントディレクトリにあるテキストファイルを全部catして、標準出力する
  • ただcatしてるだけではなく、これ自体がスクリプトになってて、それを実行すれば元のファイル構成に展開してくれる。
$ ls
foo.c boo.c
$ bundle * > expand.sh

で、'expand.sh'はfoo.cとboo.cを生成するスクリプトになる。ということだ。

用例として、メールでプログラム群を送りたいときとかに使うが、 今の時代だと、メールにファイルを添付できるからありがたみがあまり無い。 (テキストデータしか送れない時代には便利でしょう。)

これを拡張して、テンプレート生成プログラムにしてみた。

例えば、C言語でも何でも、ちょっと動きを確かめたいときに 何かしらのテストプロラムを書く。 しかし、毎回 *.c や Makefile を書くのが面倒なので、たいてい どっかのディレクトリにテンプレートを作って、それをコピって肉付けする。

コピーればいいんだが、テンプレート作成をスクリプトにしちゃえば持ち運びが便利。 なので、くだんのbundleを拡張してディレクトリ以下のファイルもパックできるようにした。 以下、改良版。

# !/bin/sh
# bundle: group files and directories into distribution package

bundle_file() {
    echo '#'
    echo "# $1"
    echo '#'
    echo "cat >$1 <<'End of $1'"
    cat $1
    echo "End of $1"
    echo
}

bundle_dir() {
    echo '##'
    echo "## Directory: $1"
    echo '##'
    echo "mkdir $1"
    for i in `find $i \! -type d -print`
    do
        bundle_file $i
    done
}

echo '#!/bin/sh'
for i
do
    if [ -d $i ] ;then
        bundle_dir $i
    else
        bundle_file $i
    fi
done

たとえば、Unitテストも含めたCのテンプレート

$ find .
./main.c
./Makefile
./test
./test/Makefile
./test/test.c
./test/test.h

この構成をパックしたいとする

$ bundle * > mk_tmpl_c_utest.sh

とするとディレクトリ丸ごとbundleして、mk_tmpl_c_utest.sh に出力する。 で、sh mk_tmpl_c_utest.shすれば、任意のディレクトリ以下に同じ構成を展開できる。(ただし、ディレクトリは一段目までしか見てない。)

以上。