findコマンドを使用してPerlに引数を渡すことはできますか?

findコマンドを使用してPerlに引数を渡すことはできますか?

Perlスクリプトがあります

$ cat ~/script.pl
sub main {

    my ($file) = @_;

    <STUFF>

    }

}

foreach (@ARGV) {

    main($_);

}

ディレクトリ内の~/script.plすべてのファイルを実行したいです。次のコマンドを使用してファイルのリストをインポートできます。.txt~/foo.txt~/foo

$ find ~/foo -type f -name \*.txt

どういうわけか、このコマンドを使用してこれらのファイルを私のスクリプトに渡すことはできますか?

答え1

はい、コマンドを使用してこれを行う方法はいくつかありますfind。あなたの状況を理解する上で重要だと思われる順序でいくつかリストします。

  1. スクリプトは複数のファイル名引数を受け入れているように見えるため、findこのコマンドを使用してこれを実行する最も効率的でほぼ一般的な方法は次のとおりです。

    find ~/foo -type f -name \*.txt -exec perl ~/script.pl {} +
    

    これにより、見つかったファイル名引数をできるだけ多く使用してスクリプトが実行されます。すべてのファイル名を処理する必要がある場合は、スクリプトが複数回呼び出されます。行の+終わりに。

  2. これは最も独創的で多目的な方法です。これはperl見つかった各ファイルに対して一度呼び出されるので、あなたの場合はあまり効率的ではありません。この使用法は以下に由来します。Unixの初代\;行の末尾にあるエスケープされたセミコロン()を確認してください(+上記の反対)。

    find ~/foo -type f -name \*.txt -exec perl ~/script.pl {} \;
    
  3. このコマンドは、構文が-exec ... +追加される前にファイル名または他のパラメータのリストを操作するときの効率を高めるように設計されています。これは上記の例とほぼ同じです。findxargs-exec ... +

    find ~/foo -type f -name \*.txt -print | xargs perl ~/script.pl
    

    実装がそれをサポートしている場合は、引数だけでなく-print0オプションも使用する必要があります。これにより、引数文字列の間にヌル文字が印刷され、引数がヌル文字以外のものに分割されるのを防ぐことができます。これは、ファイル名にスペースやその他の特殊文字が含まれている場合に引数が誤って分割されるのを防ぐのに役立ちます。find-0xargsfindxargsxargs

    一般的に構文を使用する方が-exec ... +良い方法です。これfindにより、ファイル名をスクリプトの引数リストに直接追加してプロセスを削除しますxargs。マニュアルページをxargs参照してください。xargs

  4. find2perlまた、同じ引数を使用して同じ操作を実行するプログラムを印刷するこのコマンドを表示することもfindできます。その後、生成されたコードをスクリプトにperl統合できます。perl以下のスクリプトでは、代わりに関数呼び出しの横にある最後の行を変更しますprint

    $ find2perl foo -type f -name \*.txt    # /*
    
    #[some preamble code removed for brevity]
    
    # Traverse desired filesystems
    File::Find::find({wanted => \&wanted}, 'foo');
    exit;
    
    sub wanted {
        my ($dev,$ino,$mode,$nlink,$uid,$gid);
    
        (($dev,$ino,$mode,$nlink,$uid,$gid) = lstat($_)) &&
        -f _ &&
        /^.*\.txt\z/s
        && print("$name\n");
    }   
    

答え2

他の答えからわかるように可能です。

私は代替案を提案したいと思います。これを行わずに組み込みのPerlを使用してください。File::Findデフォルトでは同じことを行いますが、スタンドアロンで実行できます。

たとえば、

#!/usr/bin/env perl
use strict;
use warnings;

use File::Find;

sub process {
    return unless -f;
    return unless m/\.txt$/; #regex style, not shell glob. 
    print "Found: Name of $_ as path $File::Find::name in $File::Find::dir\n"; 
}

find ( \&process, '~/foo' ); 

~/foopath()をハードコードするか、からインポートすることができます@ARGV

 find ( \&process, @ARGV ); #takes as many paths as you specify as args. 

答え3

-exec scriptName.sh {} \;うん、仕組みがある

あなたの具体的なケースでは

find ~/foo -type f -name \*.txt -exec scriptName.sh {} \;

別の方法は、空の区切り文字を使用してファイルを渡すことですxargs

この例は xargs マニュアルから直接インポートしたものです。

 find /tmp -name core -type f -print0 | xargs -0 /bin/rm -f

関連情報