62

この質問は、これから派生したものです。いくつかの歴史:私が最初にPerlを学んだとき、私はそれがより簡単であると思ったので、ほとんど常に+globではなく使用しました。その後、さまざまな投稿や読み物がそれが悪いことを示唆したので、今ではほとんどいつもを使用しています。opendirreaddirglobreaddir

この最近の質問を考えた後、私はどちらか一方の選択の理由が二の次であるかもしれないことに気づきました。それで、私はいくつかの賛否両論をレイアウトするつもりです、そして私はより経験豊富なPerlの人々がチャイムを鳴らして明確にすることができることを望んでいます。一言で言えば、(一部またはすべての場合に)好むまたは好むやむを得ない理由があるかどうかというglob質問readdirです。readdirglob

glob長所:

  1. ドットファイルはありません(要求しない限り)
  2. アイテムの注文は保証されています
  3. ディレクトリ名をアイテムに手動で追加する必要はありません
  4. より良い名前(名前だけで判断する場合は、globコンテストreaddirではありません)
  5. (ysthの回答から。以下のglob短所4を参照)存在しないファイル名を返すことができます。

    @deck = glob "{A,K,Q,J,10,9,8,7,6,5,4,3,2}{\x{2660},\x{2665},\x{2666},\x{2663}}";
    

glob短所:

  1. 古いバージョンは単純に壊れています(しかし、「古い」は5.6より前のことを意味します。率直に言って、5.6より前のPerlを使用している場合は、より大きな問題があります)
  2. stat毎回呼び出します(つまり、statほとんどの場合、無駄に使用します)。
  3. ディレクトリ名のスペースに関する問題(これはまだ本当ですか?)
  4. (ブライアンの回答から)存在しないファイル名を返すことができます:

    $ perl -le 'print glob "{ab}{cd}"'
    

readdir長所:

  1. (ブライアンの答えから)opendirプログラムで渡す(そして再利用する)ことができるファイルハンドルを返しますが、glob単にリストを返します
  2. (ブライアンの答えから)readdirは適切なイテレータであり、、、に関数を提供しrewinddirますseekdirtelldir
  3. もっと早く?(上からのいくつかの機能に基づいた純粋な推測glob。とにかくこのレベルの最適化についてはあまり心配していませんが、理論的なプロです。)
  4. エッジケースのバグが発生しにくいのはglob
  5. デフォルトですべて(ドットファイルも)を読み取ります(これも短所です)
  6. ファイルに名前を付けないように説得するかもしれません0(短所もあります-ブラッドの答えを参照してください)
  7. 誰?ビュラー?ビュラー?

readdir短所:

  1. ディレクトリ名の前に付けるのを忘れた場合は、ファイルテストを実行したり、アイテムをコピーしたり、アイテムを編集したりするときに、ビットが表示されます...
  2. とアイテムを忘れてgrepしまった場合、アイテムを数えるか、ファイルツリーを再帰的に下って行くか......
  3. ディレクトリ名の前に付けることについて言及しましたか?(補足ですが、Perl Beginnersメールリストへの私の最初の投稿は、この落とし穴に関連する古典的な「ファイルテストを含むこのコードが機能しないのはなぜですか?」という問題でした。どうやら、私はまだ苦いです。)
  4. アイテムは順不同で返送されます。これは、多くの場合、何らかの方法でそれらを並べ替えることを覚えておく必要があることを意味します。(これは、速度が向上し、実際にアイテムを並べ替える方法と必要性について考えることを意味する場合、プロになる可能性があります。)編集:恐ろしく小さいサンプルですが、Macreaddirでは大文字と小文字を区別せずにアルファベット順にアイテムを返します。DebianボックスとOpenBSDサーバーでは、順序は完全にランダムです。私はAppleの組み込みPerl(5.8.8)と自分でコンパイルした5.10.1を使ってMacをテストしました。Adobeボックスは、OpenBSDマシンと同様に5.10.0です。これはPerlではなくファイルシステムの問題なのだろうか?
  5. デフォルトですべて(ドットファイルも)を読み取ります(これもプロです)
  6. 名前の付いたファイルを必ずしもうまく処理できるとは限りません0(プロも参照してください-ブラッドの回答を参照してください)
4

10 に答える 10

43

それらの間の最も重要で最大の違いを見逃しています:globリストを返しopendirますが、ディレクトリハンドルを提供します. そのディレクトリ ハンドルを渡して、他のオブジェクトやサブルーチンが使用できるようにすることができます。ディレクトリ ハンドルを使用すると、サブルーチンまたはオブジェクトは、それがどこから来たのか、他の誰がそれを使用しているかなどについて何も知る必要はありません。

 sub use_any_dir_handle {
      my( $dh ) = @_;
      rewinddir $dh;
      ...do some filtering...
      return \@files;
      }

dirhandle を使用すると、次のアイテムを取得するだけですがseekdir、で移動できる制御可能なイテレータが得られます。glob

何でもそうですが、コストとメリットは、特定のコンテキストに適用された場合にのみ意味があります。それらは特定の用途以外には存在しません。あなたはそれらの違いの優れたリストを持っていますが、あなたがそれらをどうしようとしているのかを知らずにそれらの違いを分類することはできません.

その他の注意事項:

  • で独自のグロブを実装できますopendirが、その逆はできません。

  • glob は独自のワイルドカード構文を使用しており、それだけで十分です。

  • glob は存在しないファイル名を返すことがあります:

    $ perl -le 'print glob "{ab}{cd}"'
    
于 2009-10-01T22:39:00.857 に答える
7

glob の長所: 存在しない「ファイル名」を返すことができます:

my @deck = List::Util::shuffle glob "{A,K,Q,J,10,9,8,7,6,5,4,3,2}{\x{2660},\x{2665},\x{2666},\x{2663}}";
while (my @hand = splice @deck,0,13) {
    say join ",", @hand;
}
__END__
6♥,8♠,7♠,Q♠,K♣,Q♦,A♣,3♦,6♦,5♥,10♣,Q♣,2♠
2♥,2♣,K♥,A♥,8♦,6♠,8♣,10♠,10♥,5♣,3♥,Q♥,K♦
5♠,5♦,J♣,J♥,J♦,9♠,2♦,8♥,9♣,4♥,10♦,6♣,3♠
3♣,A♦,K♠,4♦,7♣,4♣,A♠,4♠,7♥,J♠,9♥,7♦,9♦
于 2009-10-02T02:33:33.697 に答える
6

opendirとの欠点は次のとおりですreaddir

{
  open my $file, '>', 0;
  print {$file} 'Breaks while( readdir ){ ... }'
}
opendir my $dir, '.';

my $a = 0;
++$a for readdir $dir;
print $a, "\n";

rewinddir $dir;

my $b = 0;
++$b while readdir $dir;
print $b, "\n";

コードが同じ番号を2回出力することを期待しますが、。という名前のファイルがあるため、そうではありません0。私のコンピューターでは251188Perl v5.10.0およびv5.10.1でテストされ、印刷されます。

この問題により、ファイルの存在に関係なく、空の行の束が出力されるようになります0

use 5.10.0;
opendir my $dir, '.';

say while readdir $dir;

これは常に問題なく機能しますが、次のようになります。

use 5.10.0;
my $a = 0;
++$a for glob '*';
say $a;

my $b = 0;
++$b while glob '*';
say $b;

say for glob '*';
say while glob '*';

私はこれらの問題を修正し、Perl v5.11.2に組み込まれたパッチを送信したので、Perlv5.12.0がリリースされたときに正しく動作します。

私の修正はこれを変換します:

while( readdir $dir ){ ... }

これに:

while( defined( $_ = readdir $dir ){ ...}

これにより、ファイルで機能したのと同じようreadに機能します。実際には同じコードですが、対応するifステートメントに別の要素を追加しただけです。

于 2010-03-02T17:46:08.080 に答える
6

globのように、特定の固定深度のすべてのサブディレクトリを読み取るのに便利glob "*/*/*"です。私はこれがいくつかの場面で便利であることを発見しました.

于 2010-03-01T23:30:16.510 に答える
2

グロブの長所:

3) ディレクトリ名を手動でアイテムの先頭に追加する必要はありません

例外:

say for glob "*";

--output:--
1perl.pl
2perl.pl
2perl.pl.bak
3perl.pl
3perl.pl.bak
4perl.pl
data.txt
data1.txt
data2.txt
data2.txt.out

私が知る限り、ルールglobは次のとおりです。完全なパスを取得するには、ディレクトリへの完全なパスを指定する必要があります。Perlのドキュメントはそれについて言及していないようで、ここの投稿もそうではありません.

つまり、(フル パスではなく) ファイル名だけが必要で、隠しファイル (つまり、'.' で始まるファイル) を返したくない場合globに代わりに使用できます。readdir例えば、

chdir ("../..");  
say for glob("*");
于 2009-11-14T06:44:31.600 に答える
2

小さくてシンプルなものの場合、私はglob. つい先日、それと 20 行の perl スクリプトを使用して、私の音楽ライブラリの大部分にタグを付け直しました。 glob、しかし、かなり奇妙な名前を持っています。グロブ?名前に関する限り、まったく直感的ではありません。

私の最大のハングアップreaddirは、ほとんどの人にとってやや奇妙な方法でディレクトリを扱うことです。通常、プログラマーはディレクトリをストリームとは考えず、glob が提供するリソースまたはリストと考えます。名前が良くなり、機能も良くなりましたが、インターフェイスにはまだ何かが残っています。

于 2009-10-01T22:51:34.827 に答える
2

同様に、 にFile::Slurpは という機能がありますread_dir

File::Slurpスクリプトで の他の関数をよく使用するので、read_dirこれも習慣になっています。

次のオプションもあります: err_modeprefix、およびkeep_dot_dot

于 2012-06-07T08:12:59.000 に答える
0

まず、いくつかの読書をしてください。第9.6章。Perlクックブックの議論の見出しのすぐ下に、私がうまく行きたいポイントを概説しています.

次に、 Perl ディレクトリでglobandを検索します。dosglob多くの異なるソース (ファイル リストを取得する方法) を使用できますがdosglob、Windows プラットフォームを使用している (そしてdosglobソリューションを使用している) 場合、実際にはopendir/ readdir/を使用しているためですclosedir。他のバージョンでは、組み込みのシェル コマンドまたはコンパイル済みの OS 固有の実行可能ファイルを使用します。

特定のプラットフォームをターゲットにしていることがわかっている場合は、この情報を有利に利用できます。参考までに、Strawberry Perl Portable エディション 5.12.2 でこれを調べたので、Perl の新しいバージョンまたは元のバージョンでは状況が少し異なる場合があります。

于 2011-05-19T01:15:02.347 に答える