我有一个 perl 脚本
$ cat ~/script.pl
sub main {
my ($file) = @_;
<STUFF>
}
}
foreach (@ARGV) {
main($_);
}
Run Code Online (Sandbox Code Playgroud)
我想对目录下的~/script.pl
每个.txt
文件执行~/foo
。我可以使用命令获取.txt
文件列表~/foo
$ find ~/foo -type f -name \*.txt
Run Code Online (Sandbox Code Playgroud)
我可以以某种方式使用此命令将这些文件传递给我的脚本吗?
Rob*_*rtL 11
是的,有几种方法可以使用该find
命令完成此操作。我将按照我认为对理解您的情况很重要的顺序列出一些。
您的脚本似乎接受多个文件名参数,因此使用该find
命令完成此操作的最有效且几乎通用的方法是:
find ~/foo -type f -name \*.txt -exec perl ~/script.pl {} +
Run Code Online (Sandbox Code Playgroud)
这将使用尽可能多的找到的文件名参数执行您的脚本。如果需要处理所有文件名,您的脚本将被多次调用。注意+
行尾。
这是最原始也是最通用的方法。这对您的情况来说效率较低,因为它perl
为找到的每个文件调用一次。这种用法从Unix 的早期就已经可用。请注意行尾的转义分号 ( \;
)(与+
上述相反)。
find ~/foo -type f -name \*.txt -exec perl ~/script.pl {} \;
Run Code Online (Sandbox Code Playgroud)在将-exec ... +
语法添加到之前find
,xargs
发明了该命令以帮助提高处理文件名列表或其他参数时的效率。这与-exec ... +
上面的示例几乎相同:
find ~/foo -type f -name \*.txt -print | xargs perl ~/script.pl
Run Code Online (Sandbox Code Playgroud)
如果您的实现支持它,您应该使用 的-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");
}
Run Code Online (Sandbox Code Playgroud)