このディレクトリの索引
http://hibari.2ch.net/test/read.cgi/tech/1308749241/196
#  [1] 授業単元:システムコール 
#  [2] 問題文(含コード&リンク):http://codepad.org/XAPpvt1n 
#  
#  コマンドライン引数でファイル名をn個指定し、 ファイル1からファイルn-1まで
#  の内容を連結し、 その結果をファイルnに書き込むプログラムを書け。 
#  ただし、標準入力と標準出力を当該のファイルにリダイレクトした状態で
#  UNIX標準コマンドを実行することで行うこと。 入力ファイルに関して
#  エラーが発生した場合、 そこで処理を終了せず、残りのファイルの処理を
#  続けること。 ただし、以下のオプションをとることができるようにせよ。
#  
#  -a
#      書き込む際に、 ` を *' に、 ~ を *^ に、 それぞれ変換する。 
#  -b
#      書き込む際に、 { を *[ に、 } を *] に、
#      | (縦棒)を *\ (アスタリスク バックスラッシュ)に、 それぞれ変換する。 
#  -l
#      書き込む際に、 アルファベット小文字を、 対応する大文字の
#      前に * (アスタリスク)を添えた二文字に変換する。 
#  
#  注意1
#      ファイルをcloseした後に同名のファイルをopenすると、セキュリティ上の
#      問題が生じる。出力のリダイレクトで、そのようなことにならないよう
#      注意してプログラミングすること

'コマンドライン引数でファイル名をn個指定し、ファイル1からファイルn-1までの内容を連結し、その結果をファイルnに書き込む' :-
        'オプションならび・ファイル名ならび・出力ファイル名の取得'(_オプションならび,_ファイル名ならび,_出力ファイル名),
        フィルタの定義(_オプションならび),
        'ファイル1からファイルn-1までの内容を連結し、その結果をファイルnに書き込む'(_ファイル名ならび,_出力ファイル名).

'オプションならび・ファイル名ならび・出力ファイル名の取得'(_オプションならび,_ファイル名ならび,_出力ファイル名) :-
        user_parameters(_ユーザパラメータ),
        append(_オプションまたはファイル名ならび,[_出力ファイル名],_ユーザパラメータ),
        オプションとファイル名の分離(_オプションまたはファイル名ならび,_オプションならび,_ファイル名ならび),!.

オプションとファイル名の分離([],[],[]) :- !.
オプションとファイル名の分離([_オプション指定|R1],[_オプション指定|R2],_ファイル名ならび) :-
        sub_atom(_オプション指定,0,1,_,'-'),
        オプションとファイル名の分離(R1,R2,_ファイル名ならび),
オプションとファイル名の分離([_ファイル名|R1],R2,[_ファイル名|R3]) :-
        \+(sub_atom(_オプション指定,0,1,_,'-')),
        オプションとファイル名の分離(R1,R2,R3),!.

'ファイル1からファイルn-1までの内容を連結し、その結果をファイルnに書き込む'(_ファイル名ならび,_出力ファイル名) :-
        open(_出力フィル名,write,Outstream),
        順にファイルを呼び出し指定された変更をしながら出力する(Outstream,_ファイル名ならび),
        close(Outstream).

順にファイルを呼び出し指定された変更をしながら出力する(Outstream,[]) :- !.
順にファイルを呼び出し指定された変更をしながら出力する(Outstream,[_ファイル名|R]) :-
        open(_ファイル名,read,Instream),
        フィルタを通しながら出力する(Instream,Outstream),
        close(Instream),
        順にファイルを呼び出し指定された変更をしながら出力する(Outstream,R).

フィルタを通しながら出力する(Instream,Outstream) :-
        at_end_of_stream(Instream),!.
フィルタを通しながら出力する(Instream,Outstream) :-
        get_char(Instream,_文字),
        フィルタ(_文字,_変換された文字列),
        writef(Outstream,'%t',[_変換された文字列]),
        フィルタを通しながら出力する(Instream,Outstream).

フィルタの定義(_オプションならび) :-
        member('-a',_オプションならび),
        asserta((フィルタ('`','*''') :- !)),
        asserta((フィルタ('~','*^') :- !)),
        fail.
フィルタの定義(_オプションならび) :-
        member('-b',_オプションならび),
        asserta((フィルタ('{','*{') :- !)),
        asserta((フィルタ('}','*}') :- !)),
        fail.
フィルタの定義(_オプションならび) :-
        member('-l',_オプションならび),
        asserta((フィルタ(A,B) :-
                        A @>= 'a',
                        A @=< 'z',
                        to_upper(A,A1),
                        concat_atom(A1,B),!)),
        fail.
フィルタの定義(_) :-
        assertz((フィルタ(A,A))).