2016-04-24 11 views

答えて

5

readdirは、パス情報のないノード名のみを返します。パスが指定されていない場合は、ファイルテスト演算子には、現在の作業ディレクトリになりますし、現在のディレクトリが$currNode->rootDirectoryではないので、彼らは私が提案し

あなたはノードを組み合わせることFile::Spec::Functionsコアモジュールからrel2absを使用したことはありませんパスに名前を付けます。文字列連結を使用することもできますが、ライブラリ関数は、ディレクトリがスラッシュで終わっているかどうかのコーナーケースを処理します。

Perlの識別子が最も頻繁にsnake_caseであることを指摘しておく価値があります。大文字を使わないためです彼らは、特にパッケージ名のようにグローバルために予約されているような名前のように、識別子の最初の文字のために避けるべきである

私はあなたのサブルーチンが別の方法で設定することで、この

use File::Spec::Functions 'rel2abs'; 

sub do_search { 
    my ($curr_node) = @_; 
    my $dir   = $curr_node->rootDirectory; 

    opendir my $dh, $dir or die qq{Unable to open directory "$dir": $!}; 

    while (my $node = readdir $dh) { 
     next if $node eq '.' or $node eq '..'; 

     my $fullname = rel2abs($node, $dir); 

     print "File:  $node\n" if -f $fullname; 
     print "Directory $node\n" if -d $fullname; 
    } 
} 

ようになっているはずだと思います現在の作業ディレクトリを読み込み中のディレクトリにコピーします。その方法は、ファイルパスを操作する必要はありませんが、あなたは保存し、前に、それは

Cwdコアモジュールはgetcwdを提供し、あなたのコードは、この

use Cwd 'getcwd'; 

sub do_search { 
    my ($curr_node) = @_; 

    my $cwd = getcwd; 
    chdir $curr_node->rootDirectory or die $!; 

    opendir my $dh, '.' or die $!; 

    while (my $node = readdir $dh) { 
     next if $node eq '.' or $node eq '..'; 

     print "File: \n" if -f $node; 
     print "Directory $node\n" if -d $node; 
    } 

    chdir $cwd or die $!; 
} 
のようになります。変更した後、元の作業ディレクトリを復元する必要があります
+0

与えられたソリューションをありがとう。最初の1つは私の問題を解決した:) –

1

このCPANモジュールを使用すると、すべてのファイルとサブディレクトリを再帰的に取得できます。

use File::Find;   

    find(\&getFile, $dir); 
    my @fileList; 

    sub getFile{ 
     print $File::Find::name."\n"; 
     # Below lines will print only file name. 
     #if ($File::Find::name =~ /.*\/(.*)/ && $1 =~ /\./){ 
      #push @fileList, $File::Find::name."\n"; 
     } 
+0

これは実際にOPの問題を解決するものではありません。 – Borodin

+1

私は、既に最適化されているため問題を解決しているので、独自のコードを書くのではなく、最初にCPANモジュールを使うべきです。 – AbhiNickz

+0

それはかなり無関係です。あなたはOPがPythonを代わりに使うべきだと思うかもしれませんが、Pythonソリューションは有用ではありません。あなた自身のコードに何が間違っているのか理解させる助けにはなりませんでした。また、非再帰的解決が必要なとき。あなたの出力は元のコードのようなものではなく、使用されていない配列と解読されたセクションがあります。これは貧弱な解決策です – Borodin

1

すでに答えられていますが、実装の詳細を気にしないほうが便利で、そのような詳細を隠すためにいくつかのCPANモジュールを使うことができます。

このうちの1つは素晴らしいPath::Tinyモジュールです。

としてあなたのコードは次のようになります。childrenメソッドが自動的に...を除く

use 5.014;   #strict + feature 'say' + ... 
use warnings; 
use Path::Tiny; 

do_search($_) for @ARGV; 

sub do_search { 
     my $curr_node = path(shift); 
     for my $node ($curr_node->children) { 
       say "Directory : $node" if -d $node; 
       say "Plain File : $node" if -f $node; 
     } 
} 

-fのテストは、実際のfilesの場合にのみtrueとなることをご理解ください。例えば、上記のコードでは、symlinks(実際のファイルを指すポイント)、またはFIFOというファイルは除外されています。このような "ファイル"は普通はオープンで読み込めます。したがって、-fの代わりにいつも便利です-e && ! -dテストを使用してください(たとえば、ディレクトリは存在しますが、ディレクトリは存在しません)。

Path::Tinyにはいくつかの方法があります。例えば ​​- あなたはis_file方法は通常DWIMある

 for my $node ($curr_node->children) { 
       print "Directory : $node\n" if $node->is_dir; 
       print "File  : $node\n" if $node->is_file; 
     } 

を書くことができする:-e && ! -dPath::Tinyあなたも簡単にiterator方法を使用してツリー全体を歩いて、あなたの機能を拡張することができ使用

:上記

use 5.014; 
use warnings; 
use Path::Tiny; 

do_search($_) for @ARGV; 

sub do_search { 

    #maybe you need some error-checking here for the existence of the argument or like... 

    my $iterator = path(shift)->iterator({recurse => 1}); 
    while(my $node = $iterator->()) { 
     say "Directory : ", $node->absolute if $node->is_dir; 
     say "File  : ", $node->absolute if $node->is_file; 
    } 
} 

は、再帰的なダウン与えられた引数からすべてのファイルとディレクトリのタイプを印刷し...

など... Path::Tinyは本当にインストールしておく価値があります。

関連する問題