Perl opendir() は 1 つの操作しか許可しませんか?

Perl opendir() は 1 つの操作しか許可しませんか?

opendir()私は私に理解していないPerl関数で奇妙な問題を見つけました。

次の例では、Perlは$ pathで指定されたディレクトリを開き、すべてのサブディレクトリ名を抽出します。

opendir(my $dh, $path) or die "can't opendir $path: $!";
my @dirs = grep { ! /^[\.]{1,2}$/ && -d "$path/$_" } readdir($dh);
closedir($dh);
foreach my $d (@dirs) {
   print $encoder->encode($d);
}

この例では、Perlは$ pathで指定されたディレクトリを開き、すべてのファイル名を抽出します。

opendir(my $dh, $path) or die "can't opendir $path: $!";
my @files = grep { ! /^[\.]{1,2}$/ && -f "$path/$_" } readdir($dh);
closedir($dh);
foreach my $f (@files) {
   print $encoder->encode($f);
}

しかし、次のコードが見つかりました。ただ印刷ディレクトリ:

opendir(my $dh, $path) or die "can't opendir $path: $!";
my @dirs = grep { ! /^[\.]{1,2}$/ && -d "$path/$_" } readdir($dh);
my @files = grep { ! /^[\.]{1,2}$/ && -f "$path/$_" } readdir($dh);
closedir($dh);

foreach my $f (@files) {
   print $encoder->encode($f);
}
foreach my $d (@dirs) {
   print $encoder->encode($d);
}

grep上記の例では、2行を交換するときにPerlに@files最初に割り当てるようにした場合、Perlはただ文書を印刷します。

何してるの? !

次のコードを使用してファイルとディレクトリを印刷する回避策を見つけました。

opendir(my $dh, $path) or die "can't opendir $path: $!";
my @dirs = grep { ! /^[\.]{1,2}$/ && -d "$path/$_" } readdir($dh);
closedir($dh);

opendir(my $dh, $path) or die "can't opendir $path: $!";
my @files = grep { ! /^[\.]{1,2}$/ && -f "$path/$_" } readdir($dh);
closedir($dh);

foreach my $f (@files) {
   print $encoder->encode($f);
}
foreach my $d (@dirs) {
   print $encoder->encode($d);
}

しかし、スクリプトを動作させることはできますが、まだわかりません。なぜPerlはここでも同じように動作します。私の理解によると、opendir()ディレクトリを開いて最初の引数にハンドルを割り当てることですclosedir()。それでは$dh、ハンドルが閉じられていないと、なぜ複数の操作を実行できないのですか?

追加情報:

$ perl --version
This is perl 5, version 26, subversion 1 (v5.26.1) built for x86_64-linux-gnu-thread-multi

$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 18.04.4 LTS
Release:        18.04
Codename:       bionic

WindowsのLinuxサブシステムでこのコードを実行しています。

ベストアンサー1

私は使用しますrewinddirスキャン間。

Perlのディレクトリ検索機能(Perlの他の多くの機能と同様)は、Cランタイムの上にある薄い層です。 開くディレクトリストリーミングでは、次のことができます。アイテムを読むディレクトリ内の一度に1つ以上。しかし、一度読んでみると次のようになる。完璧。目次をもう一度読みたい場合は、rewinddirそうすることができます。

比較のために POSIX(C) へのリンクがあります。opendirreaddirそしてrewinddir

おすすめ記事