2016-03-20 10 views
1

自分自身で学習しますが、UNIX findコマンドの出力を配列ではなくハッシュにする方法を知りたかったのです。Unixのfind(1)を配列ではなくハッシュに出力する

@file_array= qx(find/-path '/{directory_path}/*' -type f -maxdepth 3 
       -name "{extension list}" 2>/dev/null); 

しかし、私はこのような何かをしたい:

私はこの作品を知っている

$variable = qx(find/-path '/{directory_path}/*' -type f -maxdepth 3 
       -name "{extension list}" 2>/dev/null); 
       $hash_file{$some_extension} = $variable; 

は、私は(まだ始まったばかりの学習を)perlのために新しいですが、任意の助けをいただければ幸いです。例えば

perl -E 'map { $filehash{$_} = undef } 
     qx(find ./ -type f -maxdepth 3 2>/dev/null) ; 
     say keys %filehash ;' 

をあなたは可能性:

+1

'find'を呼び出す特別な理由はありますか? 'File :: Find'と' File :: Find :: Rule'はかなり効果的です。 – Sobrique

+1

'$ variable = qx(...)'は、配列の場合と同じように、応答文字列全体を行に分割するのではなく、スカラ変数に置きます。 '$ hash_file {$ some_extension} = $ variable'は、' $ some_extension'の値に応じて、その文字列をハッシュ要素にコピーします。しかし、あなたが実際にやろうとしていることは不明です。あなたのハッシュで何をしたいですか?あなたは名前のリストを拡張子でフィルタリングしようとしていると思いますか? – Borodin

+1

はいボロディンはまさに私がやろうとしていることです。どのようにそれを行うことができます上の任意のポインター? – Milania

答えて

-1

あなたがキーとしてファイル名とハッシュを作成するためにmap()組み込み関数を使用することができますし、undefまたは1に値を設定するか、または他のいくつかのより便利な値

perl -MFile::Basename -E ' 
     map { chomp; $filehash{$_} = (fileparse($_, qr/\..[^.]*$/))[2] } 
     qx(find ./ -type f -maxdepth 3 2>/dev/null) ; 
     say "$_ has $filehash{$_} extension" for keys %filehash ;' 

あなたは、その後でフィルタリングできます。各ハッシュキーの値として、ファイルの拡張子(File::Basenameからfileparse()と拡張子をつかむ)を使用します。

perl -MFile::Basename -E ' 
     map { chomp; $files_ext{$_} = (fileparse($_, qr/\..[^.]*$/))[2] } 
     qx(find ./ -type f -maxdepth 3 2>/dev/null) ; 
     for $k (keys %files_ext) { say $k if $files_ext{$k} eq ".pdf" } ;' 

あなたは、スクリプトとしてこれを書き換えることができます:

use v5.22; 
use File::Basename ; 
use List::Util 'any'; 

my %files_ext ; 
my @ext = qw(.doc .xls) ; 
my @list = qx(find ./ -type f -maxdepth 3 2>/dev/null) ; 

map { 
    chomp; 
    $files_ext{$_} = (fileparse($_, qr/\..[^.]*$/))[2] 
} @list ; 

for my $k (keys %files_ext) { 
     say $k if (any { $_ eq $files_ext{$k} } @ext) ; 
} 

しかし、ファイルではなくあなたがあなたがファイルを見つけましょう様々なモジュールのいずれかを使用することができ、このようにフィルタリングするハッシュを構築しますシステムコマンドを実行せずにperlを使用してください。。例えば、File::Findには、コアperlディストリビューションが付属しています。 CPANから私のお気に入りのひとつはPath:::Iterator::Ruleです。あなたの質問は、findの出力をハッシュに追加する方法を尋ねるので、私の答えはそのアプローチに焦点を当てています。

Path::Iterator::Ruleを使用してファイルを検索し、上記のように結果をフィルタリングするスクリプトです。ファイルの大規模なセットで

use File::Basename ; 
use List::Util 'any'; 
use Path::Iterator::Rule; 

my @exts = qw(.doc .xls);  
my $rule = Path::Iterator::Rule->new()->max_depth(3); 

my @dirs = $rule->all(".") ; 

for my $file (@dirs) { 
    if (any { $_ eq (fileparse($file, qr/\..[^.]*$/))[2] } @exts) { 
    print "$file \n" ; 
    } 
} 

フィルタリング部(すなわちany()への呼び出しを->all_fast()->all()方法を交換するか、シフトすることにより、高速、これは(Path::Iterator::RuleドキュメントのPERFORMANCEセクションを参照)することが可能であってもよいですおよびfileparse())を、匿名サブルーチンsub{ ...}を使用してフィルタされたファイルのリストを直接構築するカスタムルールに変換します。 「怠惰」イテレータ方法->iter()または->iter_fast()を使用する代わりに、リストインターフェースにも役立つようです

:Unixのfind()にシステムコールを使用して、私のシステムで

use File::Basename; 
use List::Util 'any'; 
use Path::Iterator::Rule; 

my @exts = qw(.doc .xls); 
my $rule = Path::Iterator::Rule->new()->max_depth(3); 

$rule->and(
    sub { 
    my $ext = (fileparse($_, qr/\..[^.]*$/))[2]; 
    any { $_ eq $ext } @exts; 
    } 
); 

my $next = $rule->iter_fast("."); 

while (defined(my $file = $next->())) { 
    print "$file\n"; 
} 

は、すべての最速です。しかし、ファーストは必ずしも「ベスト」とは限りません。 perlモジュールは、システムコマンドの出力を単純にスラップするだけでは得られないエラー処理と安全性を提供します。

その他の参考資料

  • Finding files with Perlは、より具体的なFile::Find質問にいくつかの良い反応があり、関連セクションでいくつかの良いリンクがあります。

  • あなたの質問は、より一般的にはperlのデータ構造についてのものであるため、システム上で利用可能な「Perlデータ構造クックブック」のドキュメントをperldoc perldscとして読んでみたいでしょう。ここで

0

は迅速&汚い先端がTRとのトリックはhereからである

#!/usr/bin/env perl 

use strict; 
use warnings; 

use File::Find; 
use Data::Dumper; 

my $Input  = shift @ARGV; 
my @SuffixList = qw(\.txt \.doc \.xls \.csv); 
my $Suffixes = join '|', @SuffixList; 
my $Sources = {}; 
my $MyDepth = 5; 

find({ 
    wanted => sub { my $Depth = tr!/!!; 
        push @{ $Sources->{$1} }, $_ if ($_ =~ m{($Suffixes)\z}xms 
        && $Depth < $MyDepth) 
       }, 
    no_chdir => 1, 
}, $Input); 

print Dumper $Sources; 

です。

関連する問題