WEB相談室

Webページ作成に関しての何でも掲示板です。

タイトル:日ごとのデータ

0:[投稿] 聖魔 [2002/12/02 12:07 ][環境:WIN+IE WIN系+Perl]

お世話になります。

2002年12月1日に、時間を取得して、2002年11月30日に変えるには
どうしたらいいでしょうか?

昨日のデータとか、3日前のデータとかを、ファイル名を日付にして
保存しておき、「何日前」とかのボタンを押すと、現在から
「何日前」のデータを表示し、7日以上前のデータを削除
というふうにしたいです

宜しくお願いします。


1:[回答] 薫 [2002/12/02 13:02 ]

【1】
time関数(1970/1/1からの秒数を返す)で秒数を取得
 ↓
「何日前」の秒数を引く
例)3日前 = 60秒×60分×24時間×3日間
 ↓
localtimeで変換


【2】
timeで取得した秒をlocaltimeで変換
 ↓
日付から「何日前」を引く
 ↓
ありえない日付(0日など)を判別する

こんなところでしょうか?


2:[質問] 聖魔 [2002/12/02 18:16 ]

レスありがとうございます。

無事、「何日前」を出すことが出来ました。

すみませんがもう一つお願いします。

いま、30日前まで表示できるようにしているのですが、
30日以前のログファイルを消すにはどうすればいいでしょうか?

ファイル名は
「年月日」で付けていて、やり方は薫さんの【1】の方法です
宜しくお願いします


3:[回答] 薫 [2002/12/03 09:57 ]

「perl ファイル 削除」などのキーワードで検索してみましょう。
# 検索を上手く使いこなせると便利ですよ :-)

> 30日以前のログファイル
例えば...
1) ディレクトリ内をログファイルのみにする
2) ディレクトリ内のファイルを、ファイル名(日付)でソートしたリストを作る
3) リストの31番目から削除をはじめる

大体こんな感じじゃないでしょうか?
2) の部分も検索すれば解説サイトが見つかります。
上手く見つけられなかったら、また書いて下さい。


4:[完了] 聖魔 [2002/12/03 11:48 ]

いつも適切な回答ありがとうございます。

自分で探す努力をしてないわけではないのですが、
キーワードがどうしても…
今までperlのところをCGIで探していたのでなかなか見つからなかったのですかね?

glob関数を見つけました。ありがとうございます。
ソースは
@filename = glob("*.log");
unlink(@filename[30]);

ほんとにありがとうございました


5:[回答] ひじ [2002/12/03 19:54 ]

「完了」となっていますが、 >>4 は間違いなので、「回答」に戻します。

1. glob関数の返り値はシェル依存です。結果がソートされる保証などありません。したがって、返り値をソートしなければなりません。
2. ログファイルが必ず31個であると仮定しているようですが、その仮定は正しくありません。何らかの理由でログファイルが30個以下、または32個以上あることがあり得ます。
3. 31番目のファイルが必ず30日以前のファイルであると仮定しているようですが、その仮定は正しくありません。何らかの理由でログファイルが作成されない日ができ、30番目のファイルが30日以前のファイルである可能性があります。

また、一般にglob関数は低速で、readdir関数を使った方がよいでしょう。
#私の場合、glob関数は使い捨てスクリプトでしか使いません
ファイル名を持って来て、timelocal関数を使って1970-1-1からの秒数を取得して、あとは
>>1 の【1】の考え方で30日以前のファイルかどうか判断して消せばいいだけです。


6:[回答] 薫 [2002/12/03 23:30 ]

> >>1 の【1】の考え方で30日以前のファイルかどうか判断して
そうですね、折角の日付判断が無駄になる所でした。
御指摘ありがとうございます。
もしも日付に関係なく、「30日分のファイルだけ残す」のであれば
>>3 の方法でも問題ないかと思います。
# ちなみに「31番目を削除」ではなく「31番目以降を削除」ですね。
# 理由は >>5 にあります


7:[回答] 聖魔 [2002/12/04 19:15 ]

ご指摘ありがとうございます

指摘していただいたとおりにopendirと、readdirを使って
ファイル名を取り出し、ソートしてのですが、
分からないことがありますので質問させてください。

ファイル名を表示すると、【.】や【..】などが表示されるのですが、
これはいったいなんですか?
これをファイル名リストから外すにはどうしたらいいでしょうか?

何度もすみませんが宜しくお願いします。


8:[回答] ひじ [2002/12/04 22:28 ]

>指摘していただいたとおりにopendirと、readdirを使って
>ファイル名を取り出し、ソートしてのですが、
ソートは行いません。readdirで返ってくるファイル名をif文で使用して30日以前のファイルか否かを判断して消すだけです。
#ソートは対象ファイル数nに対してO(n log n)の時間がかかるから、この場面では無駄に遅くなってしまいます

>ファイル名を表示すると、【.】や【..】などが表示されるのですが、
>これはいったいなんですか?
【.】は今現在いるディレクトリ自身を示し、【..】は親ディレクトリを示します。
これは消してはいけません。
if文で消去しないようにする必要があります。


9:[回答] Mr.X [2002/12/05 00:23 ]

ちなみに、日付をベースにしたファイル名による判断でなく、
「30日以上更新していないファイル」という判断であれば
ファイル演算子を使うと楽です。
こんな感じ。

unlink($file)  if (-f $file && -M $file > 30);

ま、状況と好みに応じて :)


10:[回答] 聖魔 [2002/12/05 16:36 ]

すみませんまた詰ってしまいました。

【.】や【..】を消去しないようにするには、
どのようなIf文を書けば宜しいでしょうか?

if($killdirfile = ~ /[\da-zA-Z]+/){
print "<font color=\"#ffffff\">$killdirfile</font><br>";
}
と言う風にしたのですが、わけのわからない数字が返ってきます。

宜しくお願いします。


11:[回答] ふじ [URL] [2002/12/05 16:55 ]

>>10
. .. を除外する方法は、ラクダ本の readdir のところに載っています。
いくつか方法はありますが、

@files = grep !/^\.\.?$/, readdir DIR;

とか。

ところでそもそもディレクトリは unlink しようとしてもできないので、
# unlink "." or die $!;
# とかすればわかるはず。

@files = grep { -f $_ } readdir DIR;

のようにして、ファイルのみを対象にするのもいいかも知れません。
ちょっと遅くなりそうだけど。


12:[完了] 聖魔 [2002/12/05 17:31 ]

皆様、本当にありがとうございます。
自分の書いたスクリプトは
opendir(KILLDIR,"$dirlinkfile");
     @killdirfile = grep !/^\.\.?$/,readdir KILLDIR;
    closedir KILLDIR;
    ($sec,$min,$hour,$day,$mon,$year) = localtime(time-60*60*24*31);
    #$killdirfile_a = sprintf("%d%d%d",$year+1900,$mon+1,$day);
    $year = $year + 1900;
    $mon = $mon + 1;
    $killdirfile_a = "$year$mon$day";
    foreach $killdirfile(@killdirfile){
        $killdirfile_b = $killdirfile;
        substr($killdirfile_b,-4,4)="";
        if($killdirfile_b < $killdirfile_a){
            unlink("$dirlinkfile/$killdirfile");
        }
    }

です。
とりあえず正常に動作するようです。
またお気付きの点がございましたらご指摘をお願いします

ほんとにありがとうございました。


13:[完了] ふじ [URL] [2002/12/05 17:45 ]

unlink の戻り値はチェックしておきましょう。
消したつもりだったのに消えてなかった、という事態を避けるためにも。

unlink("$dirlinkfile/$killdirfile") or die "unlink failed. $!";

die するのが嫌なら print でも warn でも、とにかく何らかのメッセージは
出しておいたほうが後後のためです。


14:[完了] 聖魔 [2002/12/05 18:16 ]

レスありがとうございます。

>unlink の戻り値はチェックしておきましょう。
>消したつもりだったのに消えてなかった、という事態を避けるためにも。
ご忠告ありがとうございます。

今後とも宜しくお願いします。


15:[回答] ひじ [2002/12/05 22:17 ]

まだバグが残ってます。

今日は2002年12月5日なので、
>$killdirfile_a = "$year$mon$day";
では $killdirfile_a eq "2002125" となります。
このファイルは12月10日に消去されます。

$killdirfile_a = sprintf("%d%02d%02d",$year+1900,$mon+1,$day);
まあ、最終的に数値比較になるから、
$killdirfile_a = ($year+1900)*10000 + ($mon+1)*100 + $day;
ぐらいでよいかと思います。


16:[回答] 聖魔 [2002/12/06 19:29 ]

報告していただきありがとうございます。

なんかへこんできますね
でも、勉強になります。

これからも宜しくお願いします。


17:[完了] 聖魔 [2002/12/06 19:30 ]

すみません完了にしてなかったです。

完了でよかったですか?

回答(必須): 状態:

お名前(必須):

e-mail:

URL:




[戻る]

ChaichanPAPA's World