![我可以使用 find 命令将参数传递给 perl 吗?](https://linux22.com/image/78720/%E6%88%91%E5%8F%AF%E4%BB%A5%E4%BD%BF%E7%94%A8%20find%20%E5%91%BD%E4%BB%A4%E5%B0%86%E5%8F%82%E6%95%B0%E4%BC%A0%E9%80%92%E7%BB%99%20perl%20%E5%90%97%EF%BC%9F.png)
我有一个 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
) 进行硬编码,也可以从@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