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
。あなたの状況を理解する上で重要だと思われる順序でいくつかリストします。
スクリプトは複数のファイル名引数を受け入れているように見えるため、
find
このコマンドを使用してこれを実行する最も効率的でほぼ一般的な方法は次のとおりです。find ~/foo -type f -name \*.txt -exec perl ~/script.pl {} +
これにより、見つかったファイル名引数をできるだけ多く使用してスクリプトが実行されます。すべてのファイル名を処理する必要がある場合は、スクリプトが複数回呼び出されます。行の
+
終わりに。これは最も独創的で多目的な方法です。これは
perl
見つかった各ファイルに対して一度呼び出されるので、あなたの場合はあまり効率的ではありません。この使用法は以下に由来します。Unixの初代。\;
行の末尾にあるエスケープされたセミコロン()を確認してください(+
上記の反対)。find ~/foo -type f -name \*.txt -exec perl ~/script.pl {} \;
このコマンドは、構文が
-exec ... +
追加される前にファイル名または他のパラメータのリストを操作するときの効率を高めるように設計されています。これは上記の例とほぼ同じです。find
xargs
-exec ... +
find ~/foo -type f -name \*.txt -print | xargs perl ~/script.pl
実装がそれをサポートしている場合は、引数だけでなく
-print0
オプションも使用する必要があります。これにより、引数文字列の間にヌル文字が印刷され、引数がヌル文字以外のものに分割されるのを防ぐことができます。これは、ファイル名にスペースやその他の特殊文字が含まれている場合に引数が誤って分割されるのを防ぐのに役立ちます。find
-0
xargs
find
xargs
xargs
一般的に構文を使用する方が
-exec ... +
良い方法です。これfind
により、ファイル名をスクリプトの引数リストに直接追加してプロセスを削除しますxargs
。マニュアルページをxargs
参照してください。xargs
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' );
~/foo
path()をハードコードするか、からインポートすることができます@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