- ベストアンサー
フォルダ内の一番新しいhtmlファイルを表示させたいです。
こんにちは。 いつもお世話になっております。 早速の質問で申し訳ないのですが、どなたかご指導 して頂けないでしょうか。 たとえば、nikkiというフォルダがあったとして、 その中に、enikki.cgi というファイルと nyuuryoku.cgiというファイルを用意してあると致します。 nyuuryoku.cgi は、アップローダーのページで、その日書いた htmlファイルをnikkiフォルダにアップ出来ると言う物です。 ここまで(アップロード出来る所まで)はなんとか出来たのです。 この後、enikki.cgi をブラウザで表示させると、nikkiフォルダ内から、 保存日時が一番新しいhtmlファイルを表示させたいのですが、 このような事は可能なのでしょうか? cgi でなくても良いのですが、可能な方法は ないでしょうか…? どうかご指導宜しくお願いします。
- みんなの回答 (6)
- 専門家の回答
質問者が選んだベストアンサー
$temp_fnm = "$dir_name/$file[$j]"; の行を $temp_fnm = "$file[$j]"; にしてください。 その後、CGI内でファイルパスとして汎用的に使えるように、と考えてしまったので、基準となるパスを付け加えていました。 それだけです、はい (^^; では、頑張ってスクリプトを完成してください。
その他の回答 (5)
- buffalomasa
- ベストアンサー率66% (70/106)
こんにちわ、#4です。 何故でしょうね? わたしの環境では問題なく表示されていますよ。 >ためしに、フォルダの中にあるファイルを >全部摘出させてみたのですが、これは、.//は >つかず、ファイル名のみが羅列出来ておりました。 > >なぜ、更新日時順に並べて一番新しいファイルを >取得した時だけ、.//がでるのでしょうか…? この意味がちょっとわからないのですが、具体的にスクリプトの変数で、どの変数の値が正常でどれがおかしいのか示してもらえるとわかりやすいのですが。 このままの意味ですと以下のようなことですか? 変換前の@rは正常にパスが記述されていて変換後の@rには変なパスが付く。 ちなみに $d = '../nikki'; これはそのままですか? また変換前の@rの例と、変換後の@rの例を示してもらえるとありがたいです。
お礼
buffalomasaさま。 こんにちは。 原因が、わかりました!! kenken_ken様に教えて頂いた回避方法をヒントに 考えていたのですが、 for (@f) { next if /^\.\.?$/; $f = "$d/$_"; push @r, $f; } の箇所を $f = "$_"; に変更しましたら、.//nikki.cgiと表示されなくなり、 nikki.cgiと表示出来るようになりました。 色々と、ご親切にありがとうございました。
- buffalomasa
- ベストアンサー率66% (70/106)
あるディレクトリ下のファイルの更新日時順でソートしたい時はシュウォーツ変換を使うと便利です。 ------------------------------------------ #!/usr/local/bin/perl $d = '../nikki'; opendir DIR, $d; @f = readdir DIR; closedir DIR; for (@f) { next if /^\.\.?$/; $f = "$d/$_"; push @r, $f; } @r = map { $_->[0] } sort { $a->[1] <=> $b->[1] } map { [ $_, -M ] } @r; print "Content-Type: text/html\n\n"; print $r[0]; exit; ------------------------------------------ @rは更新日時順でソートされています。 降順でソートしたい時は sort { $a->[1] <=> $b->[1] }を sort { $b->[1] <=> $a->[1] }に変更します。 ちなみにこれはHTMLファイルのみではなく、nikkiフォルダー内のファイル全てについて行いますので、HTMLだけの時は適宜変更して下さい。
お礼
buffalomasa様。 ご指導ありがとうございました。 教えて頂いたコードで、無事にnikki.cgi(一番最後に 更新したファイル)がブラウザに表示できました。 が、.//nikki.cgi と表示されてしまうので、 .//を無くせないかと、いじっておりました。 最初に、@f = grep(!/^\.+/,readdir DIR) と書いてみたのですが、エラーこそ出ないものの .//nikki.cgiと表示されたままだったので、 最後の、printで出力する前に、 $r[0] =~ s/[\.\/]//g; と記述してみたのですが、 nikkicgiと、.cgiの.までが消されてしまって…。 .//の3文字を一つの文字列として削除したいと 思い、$r[0] =~ s/[.//]/g;などとも記述 してみたのですが、これは Unmatched [ before HERE mark in regex m/[ << HERE ./ というエラーが帰ってきております。 ためしに、フォルダの中にあるファイルを 全部摘出させてみたのですが、これは、.//は つかず、ファイル名のみが羅列出来ておりました。 なぜ、更新日時順に並べて一番新しいファイルを 取得した時だけ、.//がでるのでしょうか…? 何度もすみません。 どうかご指導宜しくお願い申し上げます。
- kenken_ken
- ベストアンサー率33% (20/59)
えっと・・・ 下のコードを実行してみてください。 local ( @file, $dir_name, $temp_ctime, $temp_fnm, $j); local ( $device, $inode, $mode, $nlink, $uid, $gid, $rdev, $size, $atime, $ctime, $blksize, $blocks); $dir_name = "../nikki"; opendir(DIR, $dir_name); @file = readdir(DIR); $temp_ctime=0; foreach $j (0 .. $#file) { if (($file[$j] ne ".") && ($file[$j] ne "..")) { ($device, $inode, $mode, $nlink, $uid, $gid, $rdev, $size, $atime, $ctime, $blksize, $blocks) = stat("$dir_name/$file[$j]"); if ($ctime > $temp_ctime) { $temp_ctime = $ctime; $temp_fnm = "$dir_name/$file[$j]"; } } } print $temp_fnm,"\n"; このディレクトリ構成だと .cgi ファイルも対象になってしまいますが、これを対象外とする方法はわかりますよね? で、一つ訂正です。 「@file = readdir(DIR); で、フォルダ内の情報(ファイル情報の配列)を取得します。」 と書きましたが、これは、「ファイルエントリの一覧を取得」の誤りでした。すみません。
お礼
kenken_ken様。 こんばんは。何度も、丁寧に教えていただきまして ありがとうございます。 教えて頂いたコードを実行していたのですが、 Internal Server Error が出てしまっておりました。 Perlのパスも 間違えていないでしたし、シンタックもOKと 出ていたので、かなり長い時間悩んでいたのですが、 パスの後ろに、--を付けたら回避できました。 回避できた後は、buffalomasa様に教えて頂いた 方法のときと同様の、../nikki.cgiという答えが 表示され、.//だけを削除できないものかと $temp_fnm =~ s/[\.\/]//g; などと試してみたのですが、拡張子の前の.まで 消えてしまう、という所でつまずいております。 $temp_fnm =~ s/[.//]/g;などとも書いてみたのですが これはエラーでした。 ためしに、 opendir DIR,"$Dir" or die; #ディレクトリをオープン @alldir = readdir DIR; #ファイル一覧を得る close DIR; print <<"EOL"; Content-type: text/html <html> <head> <title>ファイル一覧</title> </head> <body EOL foreach (@alldir){ print $_,"<br>\n"; } print <<"EOL"; </body> </html> EOL と書いてフォルダの中にあるファイルを 全部摘出させてみたのですが、これは、.//は つかず、フォルダ内のファイル名のみが 無事羅列出来ておりました。 なぜ、一番新しいファイルを取得した時だけ、 .//がでるのでしょうか…? 何度もすみません。 どうかご指導宜しくお願い申し上げます。
- kenken_ken
- ベストアンサー率33% (20/59)
あー・・・すみません、書き方が判りにくかったようです・・・ foreach $j (0 .. $#file) { ($device, $inode, $mode, $nlink, $uid, $gid, $rdev, $size, $atime, $ctime, $blksize, $blocks) = stat("../$dir_name/$file[$j]"); } のように、配列の情報取得をループの中に入れなければなりません。 で、ループの中では前回のループで取得した$ctimeをと今取得した$ctimeを比較して、もし、今取得した$ctimeが「新しい」場合には、そのファイル名を記憶しておけば、ループを抜けたときには「最新の」ファイル名が記憶されている、という仕組みです。 ループの最初で「前回のループで取得した$ctime」をどうするか、とか、「前回のループで取得した$ctime」はどこにあるか?といったようなことはご自分で考えてみてください。
お礼
kenken_ken様。 何度もすみません。 ご指導ありがとうございます。 色々悩みつつ調べていたのですが、”前回のループで 取得した$xtime”の得方すら判らなくって…。 前回のループで取得している、という事は、 それのファイル名と更新日時を保存するログファイル を作らないといけないのかしら、とか考えたのですが、 そうすると、enikki.cgiの最初の方で、ログファイルから前回の値を引っ張ってくるコードが必要に なるのかしら…とか考えて、調べながら弄くっていた のですが、だんだんこんがらがってしまって。 煮詰まりながらも、ループで取得した$xtimeと@fileの 配列を、$xtime($jが更新日時のところなのですよね?) の数値で昇降順に並べて、一番上のファイル名だけ ひっぱってこれたらよいのではないか??と自分なりに 考えて、まず得たファイル名だけでも表示出来る所まで したいと思って、教えて頂いたコードを参考にしながら #!/usr/bin/perl #一覧を得たいディレクトリへのパス $Dir = '../nikki'; opendir DIR,"$Dir"; #ディレクトリをオープン @alldir = readdir DIR; #ファイル一覧を得る close DIR; #ファイルの最終更新日を得る @time = (stat "@alldir")[9]; (@sec,@min,@hour,@mday,@mon,@year)=localtime(@time); $year+=1900; $mon++; #最終更新日を大きい順にならべる @time = sort bynumber_rev @time; foreach (@time){ print $time[0],"\n"; } と書いてみたのですが……。 Undefined subroutine in sort at C:/Program Files/Apache Group/Apache2/htdocs/nikki/nikki2/enikki.cgi line 19.\r と出てきて、うなだれております。 根本的に、解釈の仕方が間違えているのでしょうか…。 何度もすみません。 どうか宜しくお願い申し上げます。
- kenken_ken
- ベストアンサー率33% (20/59)
perlをご存知のようですので、簡単に。 # もっと簡単な方法もあるかも知れませんが。 先ず、 opendir(DIR, "../$dir_name"); で、フォルダを開いておいて @file = readdir(DIR); で、フォルダ内の情報(ファイル情報の配列)を取得します。 ($device, $inode, $mode, $nlink, $uid, $gid, $rdev, $size, $atime, $ctime, $blksize, $blocks) = stat("../$dir_name/$file[$j]"); で、各々のファイル情報が取得でき、 $ctime に更新日時(だったっけ?)が入りますので foreach $j (0 .. $#file) { としてファイル数分繰り返して比較すれば「一番新しい」ファイルのファイル名が取得できますよね。
お礼
kenken_ken様。こんばんは。 ご指導ありがとうございます。 実は、Perlを触り始めてまだ半年にも満たなくって、しかも 本をみながらでないとわからないレベルです。 やっと掲示板などで、コードの切り張りが出来るように なった所で…。 教えて頂いた方法で、下記のように書き、nikkiフォルダに保存して 試してみました。 【記述した内容ー全文ですー】 #! /usr/bin/perl -cw #調べたいフォルダ名 $dir_name = 'nikki'; #フォルダを開く opendir(DIR, "../$dir_name"); #フォルダ内の情報(ファイル情報の配列)を取得 @file = readdir(DIR); #各々のファイル情報が取得 #$ctime に更新日時が入る ($device, $inode, $mode, $nlink, $uid, $gid, $rdev, $size, $atime, $ctime, $blksize, $blocks) = stat("../$dir_name/$file[$j]"); #ファイル数分繰り返して比較し一番新しいファイル名を取得 foreach $j (0 .. $#file) { #取得した一番新しいファイルへジャンプ print "Content-type:text/html\n\n"; print "Location: $j\n\n"; }; exit; 【内容ここまで】 すると、エラーが出てしまって、どうしたら良いのかわからなくて…。 この時間まであれこれと書籍を読んだりして考えたのですが、 どうしても判らないのです。 何度も申し訳ないのですが、ご指導願えないでしょうか。 【エラー内容】 Name "main::nlink" used only once: possible typo at C:/Program Files/Apache Group/Apache2/htdocs/nikki/enikki.cgi line 14.\r
お礼
kenken_ken様。 こんばんは。 ご指摘の通りの箇所を変更したら、.//が 無くなりました。 何度も、丁寧にご指導いただき、ありがとうございました。 Locationをつけて、無事、最新のファイルへ ジャンプさせる事も出来ました。 ありがとうございました。