- ベストアンサー
ファイルの作成と書き込み
今始めてPerlを書いているのですがつまづいている部分があります。 変数に記録されたデータをテキストファイルとして出力する部分なのですが保存するテキストファイルを上書きしないようにしてほしいのです。 私が希望する流れを簡単に説明すると・・・。 変数「$txt」にデータを記録。 ↓ フォルダー「log」に移動。(開く。) ↓ ファイル「1.txt」の存在を確認。 ↓ (存在しなければ) 「1.txt」を作成。中身は「$txt」 ↓ (存在すれば) 「2.txt」の存在を確認。 ・ ・ ・ これを10回ループ ・ 「12.txt」の存在を確認。 (存在しなければ) 「12.txt」を作成。中身は「$txt」。 (存在したら) 「1.txt」を「$txt」で上書き 説明下手なのですがどなたかわかるかたソースを教えていただけませんか?
- みんなの回答 (7)
- 専門家の回答
質問者が選んだベストアンサー
2つの命令とはBLUEPIXYさんと私の紹介した命令の事でしょうか。 つなげるという意味がわかりませんでしたが一応この二つを使って作ってみました。 処理の流れはmr_flogmanさんのを参考に1~12のファイル存在を確認しすべて存在すればソートして一番古いファイルに書き込んでます。 処理内容にあまり自信がありませんが、宜しければ参考にして下さい。 my $txt="HOGEHOGE"; my $max_file_num=12; my $name; chdir("log"); my $flg = 0; for( 1..$max_file_num ) { $name = "$_\.txt"; if( !(-e $name) ) { $flg = 1; last; } push(@files, $name); } if ( $flg != 1 ) { $name = (sort{ (stat($a))[9] <=> (stat($b))[9] || $a cmp $b }@files)[0]; } open(HDL, "> $name"); print HDL $txt; close(HDL); print "$nameにデータを書き込みました。\n";
その他の回答 (6)
- leaz024
- ベストアンサー率75% (398/526)
要するに「最新データ+11世代のバックアップ」という形で保存したい、ということですよね? ところで、「1~12.txt を使って」とのことですが、質問の方法だと保存の度に最古のファイルを探さなければならないし、使う時にも最新のファイルを探さなければなりません。 そこで提案なのですが、ファイル名の数字をデータの新鮮度とし、1.txt が最新、2.txt が1つ前の状態、3.txt が2つ前・・・、というようにしてはどうでしょうか? これなら一々ファイルの更新日時を調べる必要がありませんし、保存時も 1.txt 生成の前に 1~11.txt を 2~12.txt にリネームするだけです。 my $generations = 12; chdir "log"; # バックアップ世代の更新 for (my $src = $generations-1; $src; --$src) { my $dst = $src + 1; rename "$src.txt"=>"$dst.txt" if -e "$src.txt"; } # 最新データの保存 open FH, "> 1.txt" or die $!; print FH $txt; # $txt は、定義済みとする。 close FH; ※コードを見やすくするためインデントなどに全角空白を使っているので、コピーされる場合はタブなどに置換して下さい。
- mr_flogman
- ベストアンサー率62% (5/8)
たびたびすみません。。。 バグッたソースをまたペーストしてしまいました。。。 orz............... 正確には、 #!/usr/bin/perl -w use strict; my $txt="HOGEHOGE"; my $max_file_num=12; my $name; chdir "log"; my $flg = 0; for(1..$max_file_num) { $name = "$_".".txt"; if( -f $name) { print "$_.txtは存在します\n"; } else { print "$_.txtにデータを書き込みました。\n"; open HDL, " > $name" or die $!; print HDL $txt; close HDL; $flg = 1; last; } } if ( $flg != 1 ) { open HDL, "/bin/ls -rt1 *.txt|/bin/tail -1|" or die $!; my $write_name = <HDL>; chomp $write_name; close HDL; open HDL, "> $write_name" or die $!; print HDL $txt; close HDL; print "$write_name"."にデータを書き込みました。\n"; }
- mr_flogman
- ベストアンサー率62% (5/8)
下の者です。 先ほどの回答バグってました。。。 #!/usr/bin/perl -w use strict; my $txt="HOGEHOGE"; my $max_file_num=12; my $name; chdir "log"; for(1..$max_file_num) { $name = "$_".".txt"; if( -f $name) { print "$_.txtは存在します\n"; } else { print "$_.txtにデータを書き込みました。\n"; open HDL, " > $name" or die $!; print HDL $txt; close HDL; } } open HDL, "/bin/ls -rt1 *.txt|/bin/tail -1|" or die $!; my $write_name = <HDL>; chomp $write_name; close HDL; open HDL, "> $write_name" or die $!; print HDL $txt; close HDL; print "$write_name"."にデータを書き込みました。\n";
- mr_flogman
- ベストアンサー率62% (5/8)
お使いのOSがUNIX系だったら、以下の方法が簡単かもしれません。 もしそうでなければ、ak9457さんのおっしゃるとおり、 stat関数を使用して、日付、ファイル名の順で、ソートするロジックを作って、一番古い日付で、もし同一日付だったら、1番若い番号の順にデータを上書きするのがよいと思います。 #!/usr/bin/perl -w use strict; my $txt="HOGEHOGE"; my $max_file_num=12; my $name; chdir "log"; for(1..$max_file_num) { $name = "$_".".txt"; if( -f $name) { print "$_.txtは存在します\n"; } else { print "$_.txtにデータを書き込みました。\n"; open HDL, " > $name" or die $!; print HDL $txt; close HDL; } } open HDL, "/bin/ls -rt1 *.txt|/bin/tail -1|" or die $!; my $write_name = <HDL>; chomp $write_name; close HDL; open HDL, "> $write_name" or die $!; print HDL $txt; close HDL; print "$write_name"."にデータを書き込みました。\n";
- ak9457
- ベストアンサー率100% (1/1)
(stat($filename))[9]で最終更新日を得られるのでこれをつかってみてはいかがでしょうか。
補足
2つの命令をつなげてみようと思っているのですが どうも上手くつながりません。 どうすれば上のような処理ができるのでしょうか。
- BLUEPIXY
- ベストアンサー率50% (3003/5914)
1~12のファイルが全て存在するとき、 常に1.txtだけに出力されるような気がしますが、 それは、置いておいて カレントディレクトリを移動するには chdir "log"; の様にします。logの部分はフルパスで。 -e "1.txt" でファイルが存在する場合(真:1)ということになります
補足
あっ、そうですね。 1~12のファイルが全て存在する場合 古い順に上書きしていきたいのですがどうすれば 良いのでしょうか。
お礼
みなさん有難う御座いました。 ポイントについては投稿順につけさせていただきました。 leaz024さん、ポイントつけられませんでした。 すいません。 結果的にどの方法を採用するかはまだ決められないのですがleaz024さんの方法も便利かなと思っています。 有難う御座いました。