perlの質問です


実は
http://q.hatena.ne.jp/1224804216
の続きなのですが。

一番最近作成されたファイルとその1つ前に作成されたファイルをperlプログラムで比較して計算しあるファイルを出力したいと思っています。
http://q.hatena.ne.jp/1224804216では1日毎にダウンロードしその日の日にちをファイル名にしてますが、実際には1時間おきとか変えてみたいと思っているので上記のような質問になりました。)

前もって指定したファイル名で2つのファイルを比較し計算し前もって指定したファイル名で出力するperlプログラムは出来上がっています。

まず行いたいのは自分で指定せずに自動的に最近作られたファイル2つを指定してファイルをopenすること。
また出力ファイルがありますが、それが最近作られたファイルになってしまうことを避けるための方法
(例えば別フォルダ)と出力ファイルを自動的に日付に関連した名前で作ることです。

10月27日に自動的にやりたいこと(以下は1日毎)

open(READ1,"081027.log")||die "can't open file";
open(READ2,"081026.log")||die "can't open file";
~計算~
open(WRITE1,">081027.txt")||die "can't open file"; //これでは別フォルダになりません。

回答の条件
  • 1人2回まで
  • 登録:2008/10/27 11:21:49
  • 終了:2008/10/29 08:53:20

回答(5件)

id:pahoo No.1

pahoo回答回数5960ベストアンサー獲得回数6332008/10/27 12:47:31

ポイント5pt

大まかな流れを紹介します。

  1. opendir, readdir, closedir を使って、指定したディレクトリのファイル一覧を取得する。
  2. そのファイル一覧から2つ取り出して、比較計算する。(すでにプログラムがある)
  3. 出力結果を別名で保存する。後日、同じプログラムで利用しないのであれば、別ディレクトリに格納するのがいいでしょう。ファイル名は、現在日時から発生すればよいと思います。
id:zzz_1980 No.2

zzz_1980回答回数492ベストアンサー獲得回数642008/10/27 16:40:48

ポイント5pt
#!/bin/sh
DIR="/tmp"
F=`ls [0-9]*.log|sort|tail -2`
RESULT=`echo $F|sed '-e s/.log//g'|sed '-e s/ /-/'`.dat
#
echo $F $DIR/$RESULT
#
exit 0

これで、日付のついたlogファイルから新しいもの2個と、それらをつないだ出力データファイル名を生成しますので、 

perl スクリプトを改造して引数を三つ (log1,log2,出力ファイル)とるようにしたうえで、

echo のところと 置き換えてください。

出力先ディレクトリは DIR を書き換えてください。

teraterm の log ファイル名は年月日時分秒にしたほうがいいかも。

やってることは pahoo さんの回答と同じです。

sed を2回呼ぶのはいけてないなぁ。

id:zzz_1980 No.3

zzz_1980回答回数492ベストアンサー獲得回数642008/10/27 18:08:42

ポイント50pt
#!/usr/bin/perl
$dir='/tmp';
@i=(`ls [0-9]*.log|sort -r`);
open(READ1,$i[0])||die "can't open file #1";
open(READ2,$i[1])||die "can't open file #2";
$i[0] =~ s/.log\n//;
$i[1] =~ s/.log\n//;
$result=sprintf(">%s/%s-%s.dat",$dir,$i[0],$i[1]);
open(WRITE1,$result)||die "can't open file #3";
#~計算~
close READ1;
close READ2;
close WRITE1;

ls と sort を呼び出してるのはいんちきだけどこれで勘弁してください。

改行を切り捨てるのは windows だとうまくいかないかも。

id:haruo-31 No.4

haruo-31回答回数80ベストアンサー獲得回数102008/10/28 01:49:48

ポイント20pt

シェルスクリプトとの合わせ技が一番楽でしょうね・・・といいつつ全部perlでやってみた。

opendir DIR, "./";

my %files;
foreach (grep {/.$/} readdir(DIR)) {
	$files{(stat($_))[9]} = $_;
}

($file1, $file2) = map {$files{$_}} (reverse(sort(keys(%files))))[0 .. 1];

print "$file1 $file2\n";

opendir DIR, "./" の ./ を目的のパスに、grep {/.$/} を grep {/\.log$/i} として実行するとfile1に最終更新日が最新のファイル、file2にfile1の次に新しいファイルのファイル名(拡張子が".log"のファイル)がセットされます。

open F1, "<", $file1 or die "$! abort.";
open F2, "<", $file2 or die "$! abort.";

use Time::Piece; #便宜上ここで書きますが、これは行頭で宣言してください。
my $t = (localtime)->ymd;
mkdir $t;
open OUT, ">", $t.'/'.$out or die "$! abort."; 

#hoge fuga;

close OUT;
close F1;
close F2;

Time::Pieceが使えなかったり思っていた書式と違うなら、$tの設定を下記に変えればyyyyMMdd形式になります。

my ($year, $month, $day) = (localtime(time))[5,4,3];
my $t = sprintf("%04d%02d%02d", $year+1900, $month+1, $day)

あー、すっきりした。

id:aki1960 No.5

aki1960回答回数256ベストアンサー獲得回数82008/10/27 15:38:53

ポイント20pt

こんなカンジで、対象ディレクトリから最新と、次の最新が取り出せるはず。

取り出す拡張子を(.log)から探すので、(.txt)が混在しても対象になりません。

  • ここから --------------------------------------------

$dir = "./logsave"; # 対象ディレクトリ

# 対象ディレクトリ全てのファイルを配列に読み込み

@files = readdir(DIR);

foreach $file ( @files ) {

# ディレクトリ(.)と(..)を対象外とする

if (("." ne $file) && (".." ne $file)) {

eval { opendir( SDIR ,"$dir/$file"); };

if (!$@) {

# 配列からファイル名(.log)を読み込み

@sfiles = grep { /\.log$/ } readdir(SDIR); # ここで対象を(.log)に限定

foreach $sfile ( @sfiles ) {

$mtime = substr("$file$sfile", 0, 6); #ファイル名から日付時刻部分を抽出(YYMMDD)

if ($newesttime < $mtime ) {

# 最新が見つかった時の処理

$nextnewestfile = $newestfile; #最新を、2番目にする

$newesttime = $mtime;

$newestfile = "$dir/$file/$sfile";

}

}

}

closedir( SDIR );

}

}

closedir( DIR );

print "$newestfile\n"; #最新

print "$nextnewestfile\n"; #次の最新

  • ここまで --------------------------------------------
  • id:zzz_1980
    b shell 併用でも構いませんか。
  • id:labtest
    >pahooさん

    回答ありがとうございます。試してまた分からなかったら質問させて下さい。

    >zzz 1980さん

    b shell併用でも構いません。もし良かったらご回答お願いします。
  • id:zzz_1980
    引数をうけとるほうは $ARGV[] を使ってください。
    #!/usr/bin/perl
    print $ARGV[0],$ARGV[1],$ARGV[2]
  • id:labtest
    >zzz 1980さん

    実はshellスクリプトはほとんど使ったことなくて

    >perl スクリプトを改造して引数を三つ (log1,log2,出力ファイル)とるよう
    >にしたうえで、echo のところと 置き換えてください。

    の意味が分からないです。具体的に教えて下さい。よろしくお願いします。

    perlの引数を3つにすることは出来ますが・・・。
  • id:zzz_1980
    echo $F $DIR/$RESULT
    をそっくりそのまま
    perlscript $F $DIR/$RESULT
    としてください。sh script 中の変数 $F にはスペース区切りでファイル名が二つはいっています。
    perl「だけ」で書いたほうが移植性がいいんですけどね。
  • id:zzz_1980
    perl のなかでls と sort するようにしてみました。確認環境が unix なのでwindows上で使うには突っ込みどころ満載ですが…
  • id:labtest
    >zzz 1980さん

    回答ありがとうございます。
    開発環境がwindows+cygwinです。とりあえず明日以降試してみますね。
  • id:labtest
    みなさま、ご回答ありがとうございます。

    全部の方法を試すのは大変なので一番良さそうな方法を試してみます。

    今の環境で動くか?拡張のしやすさ等という観点で見たいと思います。

    とりあえずお礼まで。

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

絞り込み :
はてなココの「ともだち」を表示します。
回答リクエストを送信したユーザーはいません