人力検索はてな
モバイル版を表示しています。PC版はこちら
i-mobile

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"; //これでは別フォルダになりません。

●質問者: labtest
●カテゴリ:コンピュータ インターネット
✍キーワード:10月27日 open Perl txt ダウンロード
○ 状態 :終了
└ 回答数 : 5/5件

▽最新の回答へ

1 ● pahoo
●5ポイント

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

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

2 ● zzz_1980
●5ポイント
#!/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回呼ぶのはいけてないなぁ。


3 ● zzz_1980
●50ポイント
#!/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 だとうまくいかないかも。


4 ● haruo-31
●20ポイント

シェルスクリプトとの合わせ技が一番楽でしょうね・・・といいつつ全部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)

あー、すっきりした。


5 ● aki1960
●20ポイント

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

取り出す拡張子を(.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"; #次の最新

関連質問


●質問をもっと探す●



0.人力検索はてなトップ
8.このページを友達に紹介
9.このページの先頭へ
対応機種一覧
お問い合わせ
ヘルプ/お知らせ
ログイン
無料ユーザー登録
はてなトップ