1

ディレクトリの内容を再帰的に出力するスクリプトを書きました。ただし、フォルダごとに警告が出力されます。これを修正する方法は?

サンプル フォルダ:

dev# cd /tmp/test
dev# ls -p -R
test2/テストファイル
testfile2

./test2: テストファイル3 テスト
ファイル
4

私のコード:

#!/usr/bin/perl

use strict;
use warnings;

browseDir('/tmp/test');

sub browseDir {
    my $path = shift;
    opendir(my $dir, $path);
    while (readdir($dir)) {
        next if /^\.{1,2}$/;
        if (-d "$path/$_") {
            browseDir("$path/$_");
        }
        print "$path/$_\n";
    }
    closedir($dir);
}

そして出力:

dev# perl /tmp/cotest.pl
/tmp/test/test2/testfile3
/tmp/test/test2/testfile4
/tmp/cotest.pl 行 16 の連結 (.) または文字列で初期化されていない値 $_ を使用。
/tmp /test/
/tmp/test/testfile
/tmp/test/testfile2

4

3 に答える 3

1

File::Findモジュールを使用しないのはなぜですか? Perl 5.x 以降、Perl のほぼすべてのディストリビューションに含まれています。動作がややこしいので、私のお気に入りのモジュールではありませんが、うまく機能します。

必要なことを行うサブルーチンを定義し、wanted不要なものを除外します。この場合、ほとんどすべてをwanted印刷しているので、見つかったものを印刷するだけです。

ではFile::Find、ファイルの名前は に保持され$File::Find::name、そのファイルのディレクトリは にあります$File::Find::dir。は$_ファイル自体であり、テストに使用できます。

これがあなたが望むものの基本的な方法です:

use strict;
use warnings;
use feature qw(say);

use File::Find;

my $directory = `/tmp/test`;

find ( \&wanted, $directory );

sub wanted {
    say $File::Find::Name;
}

wanted私は自分の関数をサブルーチンに入れることを好むfindので、それらは一緒です。これは上記と同等です:

use strict;
use warnings;
use feature qw(say);

use File::Find;

my $directory = `/tmp/test`;

find ( 
    sub { 
        say $File::Find::Name
    },
    $directory,
);

優れたプログラミングでは、サブルーチンで印刷しないように指示されています。代わりに、サブルーチンを使用してデータを格納して返す必要があります。残念ながら、find何も返されません。グローバル配列を使用してファイルのリストをキャプチャし、後でそれらを出力する必要があります。

use strict;
use warnings;
use feature qw(say);

use File::Find;

my $directory = `/tmp/test`;
my @directory_list;

find ( 
    sub { 
        push @directory_list, $File::Find::Name
    }, $directory );

for my $file (@directory_list) {
   say $file;
}

wantedまたは、別のサブルーチンが必要な場合:

use strict;
use warnings;
use feature qw(say);

use File::Find;

my $directory = `/tmp/test`;
my @directory_list;

find ( \&wanted, $directory );
sub wanted {
    push @directory_list, $File::Find::Name;
}

for my $file (@directory_list) {
   say $file;
}

必要なサブルーチンが、サブルーチンに対してローカルではない配列に依存しているという事実が気になります。そのため、wanted呼び出し内にサブルーチンを埋め込むことを好みfindます。

できることの 1 つは、サブルーチンを使用して必要なものを除外することです。JPG ファイルのみに関心があるとします。

use strict;
use warnings;
use feature qw(say);

use File::Find;

my $directory = `/tmp/test`;
my @directory_list;

find ( \&wanted, $directory );
sub wanted {
    next unless /\.jpg$/i;  #Skip everything that doesn't have .jpg suffix
    push @directory_list, $File::Find::Name;
}

for my $file (@directory_list) {
   say $file;
}

配列にプッシュする前に、必要なサブルーチンが不要nextなファイルに対してどのように実行するかに注意してください。@directory_list繰り返しますが、私は埋め込みを好みます:

find (sub {
    next unless /\.jpg$/i;  #Skip everything that doesn't have .jpg suffix
    push @directory_list, $File::Find::Name;
}

Find::Fileこれがあなたの質問と正確に一致しないことは承知していますが、モジュールについてお知らせし、Perl に多くの機能を追加できる Perl モジュールを紹介したかっただけです(それらについてまだ知らなかった場合)。

于 2013-04-05T16:20:36.713 に答える
1

そのコードを試していただけますか:

    #!/usr/bin/perl

    use strict;
    use warnings;

    browseDir('/tmp');

    sub browseDir {
        my $path = shift;
        opendir(my $dir, $path);
        while (readdir($dir)) {
            next if /^\.{1,2}$/;
            print "$path/$_\n";
            if (-d "$path/$_") {
                browseDir("$path/$_");
            }
        }
        closedir($dir);
    }

そのエラーが発生した場合は、変数 $_ を使用する前に、browseDir() を呼び出しているためです。

于 2013-04-05T12:51:09.323 に答える