macでperlのopen関数についての質問

このQ&Aのポイント
  • macでperlのopen関数を使ってファイルをオープンする際に、特定の場所にしかファイルを読み込まない問題が発生しています。
  • 参考書には、open関数は指定されたファイル名を持つファイルをハードディスクから探し出してオープンすると説明されていますが、実際には探し出しはしてくれないようです。
  • ファイルを自分が指定した場所からオープンする方法について、ターミナルで指示するのかコードに加えるべきなのか教えてください。
回答を見る
  • ベストアンサー

mac で perl  open関数について

お世話になります。 現在、perlの勉強中です。 状況は mac osx 10.6.6です。 使用参考書は「perl言語プログラミングレッスン[入門編]」です。 CGIは関係なしで行っております。 open関数について参考書を読みながら、 勉強をしているのですが、openでファイルをオープンするときについてなのですが、 参考書上では、「関数openは、指定されたファイル名を持つファイルをハードディスクから探し出し、オープンしようと試みます」と言う説明があるのですが、 今現在、試している文例では、特定の場所にファイルがあるときでないと、 オープンしてくれません。 文例は [test.pl] use strict; use warnings; my $filename = 'file.txt'; open(FILE, $filename) or die "$filename: $!"; while (my $line = <FILE>){ $line =~ s/ /_/g; print $line; } close(FILE); という形で、ファイルの " " (スペース)を抜き出して "_" (アンダースコア)に置き換えるという設問です。 ただ、現況は                  /Users/(myname)/Documents/test/test.pl #(myname)は私の名前のフォルダです。 にあるコードをターミナル上で実行すると、 /Users/(myname)/file.txt に配置しているときしか、読み込んでくれません。 そこから、ファイルを移動させてしまうと、 読み込んでくれないのです。 そこで、ご質問ですが、 1 「関数openは、指定されたファイル名を持つファイルをハードディスクから探し出し、オープンしようと試みます」 と参考書に記載がありましたが、実際には探し出しはしてくれないのでしょうか? それとも、自分のパソコン、コードに問題があるのでしょうか? 2 自分が指定した場所にあるファイルをオープンするには どのようにすればよいでしょうか? ターミナルで指示するのか、それともコードに加えるべきか、 ご指示くださいませ。 また、詳しい方がおられましたら、 お答えいただければと思います。 それでは失礼します。

  • Perl
  • 回答数3
  • ありがとう数3

質問者が選んだベストアンサー

  • ベストアンサー
  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.3

> 関数openが1カ所のディレクトリしか探さないという動作をすることが問題なのです。 問題ではなく、正しい動作です。 その参考書の書き方(『ハードディスクから探し出し』)が誤解を与えているかもしれません。 「openは『指定したファイルを』開こうと試みる」とした方が正確でしょう。 探したりしません。 指定したものが有るか無いかです。 指定した所に無いからといって、似たものや別の場所にあるものを、勝手に開いたりはしません。 その指定のルールとして ・ファイル名だけなら、カレントディレクトリにある同ファイル名のもの ・相対パスで指定されていたら、カレントディレクトリを起点として相対パスを辿る ・絶対パスで指定されたら、ルートディレクトリ(/)から辿る ということになっています。 ここで、どこにも「ホームディレクトリ」や「実行ファイルのあるディレクトリ」という言葉が出てこない事に注意してください。 > /Users/(myname)/Documents/test/test.pl #(myname)は私の名前のフォルダです。 > にあるコードをターミナル上で実行すると、 > /Users/(myname)/file.txt > に配置しているときしか、読み込んでくれません。 というのは ・スクリプトではファイル名だけしか指定していない→「カレントディレクトリにあるファイル」ルールが適用される。 ・ターミナルを起動したままでcdコマンドでカレントディレクトリを移動しないままに /Users/(myname)/Documents/test/test.pl などと実行している → ターミナル起動時のディレクトリ(/Users/(myname))がカレントディレクトリなので、/Users/(myname)/file.txtを指定したことになる ということだと思います。 例えば、ここで cd Documents としてから /Users/(myname)/Documents/test/test.pl としてみてください。今度は /Users/(myname)/file.txt は読み込まないはずです。cdコマンドでカレントディレクトリを /Users/(myname)/Documents へ移動したことで、 file.txtは /Users/(myname)/Documents/file.txt を指すようになります。 このあたりの概念は、ウィンドウでのGUI操作ばかりやってきた方には理解しずらいところはあるかもしれません。

dummyplugineva
質問者

お礼

ありがとう御座います!カレントディレクトリの概念と、UNIXのコマンドなど少し覚えた所、自分の質問している事が明後日の方向を向いている事に気付きました。 また、何かありましたらお願いいたします。

その他の回答 (2)

  • diszo
  • ベストアンサー率78% (32/41)
回答No.2

はずしていたらごめんなさい 実行させているディレクトリの位置を確認してみてはいかがでしょうか ターミナルからPerlのスクリプトを実行する場合に、 ホームディレクトリ(/Users/ユーザ名)から コマンド: 「perl Documents/test/test.pl」 等していませんか? ターミナルで実行している場合、 現在いる場所がカレントディレクトリになります。 上記のようなコマンドで実行した場合、 スクリプトのカレントディレクトリが「Users/ユーザ名/」になってしまい、 そのカレントディレクトリの階層にファイルが存在しないと、 ファイルが開けません。 現在のディレクトリ位置を見るには、pwdを使うとわかります。 あとは、cdで移動してください。

dummyplugineva
質問者

お礼

ありがとう御座います。 perlと一緒にUNIXの勉強も始めた所、 おっしゃってることが理解できるようになりました。 プログラムの勉強するには参考書もそうですが、 皆さんに聞いたりするのも大事ですよね! ありがとうございます!

  • nora1962
  • ベストアンサー率60% (431/717)
回答No.1

「関数openは、指定されたファイル名を持つファイルをハードディスクから探し出し、オープンしようと試みます」 というのは、ハードディスクにあるすべてのファイルから指定されたファイル名をサーチするということではありません(というか、説明が不適切ですね)。 プログラムにはプログラムを実行する時点での「カレントディレクトリ」という概念があり、そこにあるファイルしか基本的には見にいかないのです。 「/Users/(myname)/file.txt」にあるときは、Perlのスクリプトも「/Users/(myname)」で処理を行っていると思います。そこが、カレントディレクトリです。 そこ以外にあるファイルを読み書き使用する場合は明示的に場所を指定するする必要があります。 方法は二つ (1)相対パス 「./subdirectory/file.txt」のように指定します。「.」がカレントディレクトリでそこを基準にしてどこにファイルがあるかを指定するやり方です。 (2)絶対パス 「/home/何ちゃら/file.txt」のように「/」から始まる指定の仕方です。 > ターミナルで指示するのか、それともコードに加えるべきか、 場合によると思います。が、コマンドラインでファイル名を指定できるようにしておいたほうが融通が利く場面が多いかなと。

dummyplugineva
質問者

お礼

カレントディレクトリの概念とUNIXコマンドのcdとpwdを覚えた所、解決しました。 ありがとう御座いました!

dummyplugineva
質問者

補足

ご回答ありがとうございます。 ただ、現状は上記で述べているように 「 /Users/(myname)/Documents/test/test.pl  にあるコードをターミナル上で実行すると、 /Users/(myname)/file.txt に配置しているときしか、読み込んでくれません。 」 と、 関数openが 1カ所のディレクトリしか探さないという動作をすることが問題なのです。 ちなみに、test.pl を /Users/(myname)/Documents/test/test.pl 以外に /Users/(myname)/Documents/test/check/test.pl や /Users/(myname)/Documents/check/test.pl や /Users/(myname)/test.pl みたいに配置を変えたとしても、 (カレントディレクトリを変えると表現するのでしょうか?) 関数openは  「 /Users/(myname)/file.txt 」 にfile.txtを配置しているときしか、 file.txtを読み込んでくれないのです。 これは異常でしょうか? また異常でしたら直し方はありますでしょうか? ご回答いただければと思います。

関連するQ&A

  • Perl オープン関数について

    Perl オープン関数について いつもお世話になっております。 オープン関数でわからないことがあるのでご教示お願い致します。 ■test.cgi■ open(FILE, ">sled/$log") or die("error :$!"); eval{ flock(FILE, 2) }; print FILE @DATA; close FILE; ■bbstest.cgi■ open(FILE, ">>sled/$loglog") or die("error :$!"); eval{ flock(FILE, 2) }; print FILE @DATA; close FILE; 上記のtest.cgi側では「>」これが1個で書き込まれるのですが bbstest.cgi側では「>」これ1つだけですと、すべての内容がリセット され、その時入力した内容だけ残ります。 それを「>>」にすると追加はされるのですが、 test.cgi側では 上へ上へと内容は追加されていくのに対し bbstest.cgi側では 下へ下へ追加されていきます。 書込方法は、両方共 unshift(@DATA,"$NO,$tm,$TITLE,$TEXT,$PASS,$IP\n"); このようにしているのですが、 なぜ、同じ処理で、書込方法がかわるのでしょうか? 目的は上へ上へがいいのですが。。。

    • ベストアンサー
    • Perl
  • perl 5.8.8 日本語マッチ

    perl5.8.8を使っています。 日本語にマッチする正規表現を書きたいのですが、どうしてもマッチしません。 例えば、以下のファイルtest.txtから「さしすせそ」だけを抽出し、表示させたいです。 ---------test.txt-------------------------------- あいうえお かきくけこ さしすせそ たちつてと -------------------------------------------------- ----------test.pl-------------------------------- use strict; use warnings; open(FILE, 'test.txt') or die "$!"; my @file = <FILE>; close(FILE); foreach my $line (@file){ if($line =~ /^さ/){ print "$line\n"; } } ------------------------------------------------ このtest.plを実行しても「さしすせそ」を抽出することが できません。 どうしたらよいのでしょうか? 自宅の新しいバージョンのperlだとできるのですが 会社のperlは5.8.8で顧客環境でもあるのでバージョンアップも できません。 すみませんが、よろしくお願いいたします。

    • ベストアンサー
    • Perl
  • <Perl>参照配列の出力に失敗する。

    <Perl>参照配列の出力に失敗する。 お世話になります。 配列の出力部で以下のエラーが出力されます。 Use of uninitialized value in print at test2.pl line 12. -----コーディングは以下の通りです。----- #!C:\perl use strict; use warnings; my @l = (); #----------- #GetDataへCSVファイル名と、格納用配列を渡す #----------- my $cnt = &GetData("test.csv", \@l); print "COUNT -> ".$cnt; for(my $i=0; $i < $cnt; $i++){ print $l[$i]; } ################################################################## # 概   要:指定したCSVファイルをオープンしCSVデータを配列に取得する。 # パラメータ:ファイル名, CSVデータ格納用配列 # 戻 り 値:データ取得件数 ################################################################## sub GetData { my ($f, @bf) = @_; my $rcnt = 0; print "FILE NAME -> ".$f."\n"; if ( open(FP, "<${f}") ){ print "FILE OPEN -> success.\n"; @bf = split(/,/, <FP>); close(FP); $rcnt = @bf; print "CSV GET COUNT -> ".$rcnt."\n"; } return $rcnt; } -----実行結果は以下の通りです。----- D:\>perl test.pl FILE NAME -> test.csv FILE OPEN -> success. CSV GET COUNT -> 5 Use of uninitialized value in print at test2.pl line 12. Use of uninitialized value in print at test2.pl line 12. Use of uninitialized value in print at test2.pl line 12. Use of uninitialized value in print at test2.pl line 12. COUNT -> 5 -----CSVファイルの内容は以下の通りです。(ファイル名:test.csv)----- あいうえお,かきくけこ,さしすせそ,たちつてと,なにぬねの 配列の要素数が取れているので、配列内にデータは格納されているとは思っています。 出力方法をどのように正せばよいがご教示お願い致します。

    • ベストアンサー
    • Perl
  • perlで文書を読み込み検索置換したい

    MAC OS Xを使用しています。 検索置換のプログラムをperで作成し、Applescript上で呼び出したいのです。 実際はファイルメーカーのスクリプトの中でApplescriptを記述してその中で呼び出したいのです。 do shell script "perl ~.pl"という感じで使えるのではないかと 下記のようなサンプルスクリプトを見つけたのですが 内容の更新の仕方がよく分かりません。 perlについては全くの初心者でいろいろ調べたのですがよく理解できませんでした。 検索置換したいのですが、どういうふうに書けばいいのでしょうか。 (2)の部分を教えて下さい。宜しくお願いします。 use strict; use warnings; use File::Copy 'move'; # (1) ファイルの内容を読み込む my $file = 'F:\共有\PERL\test.txt'; open my $fh, '<', $file or die qq/Can't open file "$file": $!/; my $content = do {local $/; <$fh>}; close $fh; # (2) 内容の更新 ▼をリターンに置き換えたいのです。 $line =~s/▼/\n/; # (3) 一時ファイルへの書き出し my $temp_file = "$file.$$." . int(rand 10000); open my $temp_fh, '>', $temp_file or die qq/Can't open file "$file": $!/; print $temp_fh $content; close $temp_fh or die qq/Can't open file "$file": $!/; # (4) 一時ファイル名を元のファイル名に変更 move $temp_file, $file or die qq/Can't move "$temp_file" to "$file": $!/;

  • Perlでのファイル入出力、処理方法

    メモ帳で以下のようなプログラムを書きました。(file_1.plで保存しました) #!/usr/bin/perl $file="data.csv"; $cityfile="name.txt"; $outfile="data_out.csv"; open (IN, $file) or die "$!"; open (FILE, $file) or die "$!"; open (OUT, ">$outfile") or die "$!"; @city = <FILE>; ・ ・ ・ これをCygwinコマンド上で、 perl file_1.pl と入力し、Enterを押すと「No such file or directory at file_1.pl line 9.」と表示されます。 line9はopen (FILE, $file) or die "$!";という文です。 どこが間違えで、どのように修正すればよいのでしょうか。 よろしくお願いします。

  • perlのopen()で+<を使用した時の挙動が変

    open()で+<を使用すると読み書き両方ができると 理解しましたが、書き込んだ後の結果が 私が思っていた挙動と違っていました。 例えば、 ---test.pl-------------------------- open(FILE,'+<test.txt') or die "$!"; my $line=<FILE>; print FILE "ABC\n"; close(FILE); ---test.txt---- 123 456 789 --------------- を実行すると ---test.txt---- 123 ABC 789 --------------- となることを期待していましたが実際には ---test.txt---- 123 456 789 123 ABC ---------------- となっていました。 1行だけ読み出したときのファイルポインタ は2行目の先頭を指しているように思われますが なぜこのような結果になるのでしょうか。 (Windows7,ActivePerl)

    • ベストアンサー
    • Perl
  • perl サブルーチンでのファイル出力結果おかしい

    以下のコードを実行するとカレントディレクトリの配下にある すべてのファイルのリストがコンソールとファイルに出力される はずですが、コンソールに表示されているファイルの一部しか ファイルに出力されていません。 どうも、最後に do_file()を呼び出したときのファイルしか リストされていないようなのですがなぜでしょうか。 どのようにすればよいのでしょうか。 よろしくお願いします。 (Windows7, ActivePerl(v5.16.3)) ----test.pl--------------------------------------------- &do_dir('.'); sub do_dir{  open(FILE2,'>list.txt') or die "$!";  my $dirname=shift;  my $delim='/';  opendir(DIR,$dirname) or die "$!";  foreach $entry (readdir(DIR)){   next if($entry eq '.');   next if($entry eq '..');   if ($dirname=~/[\\\/]$/) {    my $delim='';   }   my $filename="$dirname$delim$entry";   if(-d $filename){    &do_dir($filename);   } else {    &do_file($filename);   }  }  close(DIR);  close(FILE2); } sub do_file{  my $filename=shift;  return unless ($filename=~/\.*$/);  print "$filename\n";  print FILE2 "$filename\n"; }

    • ベストアンサー
    • Perl
  • ファイルオープンの関数について教えてください。

    住所録保守のプログラムの宿題なんですが、ファイルオープンを関数にせずには動かせるのですが、関数にするとエラーが山のようにでます。参考書もよんでるのですがよくわかりません。明日提出なのでよろしくお願いします。                                     関数にする前の考えたプログラムは、                                            struct aaa{ char b                                                       char  c            };                                                         FILE *fp; struct aaa[100]; if((fp=fopen("c:/a.txt","rt"))==NULL) exit(0);です。                                         宿題は f_open(char *name,char *mode) を使って指定されたファイルを指定されたモードで開くという関数を作りなさい。                                                     引数 ポインタ nameはファイル名/mode はオープンモード 戻り値なし という問題です。 よろしくお願いいたします。

  • <STDIN>とARGVとの振る舞いの違いが分からず困っております。

    <STDIN>とARGVとの振る舞いの違いが分からず困っております。 Perlといいますか、プログラム初心者です。 現在、Perlでファイル処理を行おうと思っており、下記のようなスクリプトを書き、file_test.plとして保存・実行しようとしたのですが、実行時の命令の仕方により処理が出来たり出来なかったりで、困っております。どなたか、ご教授頂けませんでしょうか。 なお、使用環境はWindows XP, Active Perl 5.8.8です。 スクリプトのソース、読み込みファイル共にShift-JISです。 (ここには記載しておりませんが、処理後の吐き出しファイルはUTF-8になります) -------------------- file_test.plのソースファイル -------------------- use strict; use warnings; use encoding "cp932"; use Encode::Guess qw/euc-jp shiftjis 7bit-jis/; binmode STDIN, ':encoding(cp932)'; binmode STDOUT, ':encoding(cp932)'; binmode STDERR, ':encoding(cp932)'; my $csvname; if(defined($ARGV[0])){ $csvname = $ARGV[0]; print "csvname = $csvname\n"; #文字コード判定 my $enc = guess_encoding($csvname); ref($enc) or die "Can't guess: $enc"; print "encoding is ", $enc->name, "\n"; #UTF-8フラグチェック print utf8::is_utf8("$csvname") ? "UTF-8 Flag\n" : "not UTF-8 Flag\n"; } else{ print "input file: "; $csvname = <STDIN>; chomp($csvname); print "csvname = $csvname\n"; #文字コード判定 my $enc = guess_encoding($csvname); ref($enc) or die "Can't guess: $enc"; print "encoding is ", $enc->name, "\n"; #UTF-8フラグチェック print utf8::is_utf8("$csvname") ? "UTF-8 Flag\n" : "not UTF-8 Flag\n"; } open CSV, '<:encoding(sjis)', $csvname or die "$!"; print "FILE OPEN OK\n"; close(CSV); ------------------- file_test.plのソースファイル END ------------------- このソースを"perl file_test.pl csvfile.csv" で実行すると問題なく処理できます。 しかし、"perl file_test.pl" で実行し、あとからファイル名を入力すると、 "Invalid argument at file_test.pl line 35, <STDIN> line 1."というエラーが出ます。 (35行目はOPENコマンドの行です) しかし、 "perl -CA file_test.pl"と-CAオプションを入れ、後からファイル名を入力した場合、動作します(上述のファイルの実行と同時にファイル名を指定したものでも動きます)。 実際にはコマンドプロンプトからの実行ではなく、plファイルをダブルクリック、その後ファイル名を指定して処理を行いたいため、悩んでおります。 どのようにしたら、うまく実行できるか、ご教授頂ければ幸いです。

  • Perlの超初心者です。

    Perlの超初心者です。 mac osXを使っています。テキストエディットで、#! /usr/bin/perl print "hello world!\n";と書いてperl-test.plと保存しました。そしてターミナルを起動してperl-test.plとタイプしたのですが、-bash: perl-test.pl: No such file or directoryとなってしまいます。 試しにターミナルでperl -le "print 'hello world';"とタイプするとhello worldとかえってきました。 perl-test.plはfinderのデスクトップに保存してあります。いったいどうすればperl-test.plのファイルを実行できるのですか? 教えて下さい。よろしくお願いします。

専門家に質問してみよう