“查找”的奇怪行为

时间:2013-09-22 20:04:33

标签: bash shell grep find xargs

在我的fetch/evs/下,没有子文件夹,我有一个命令,应该列出fetch/evs/*.ev的所有不包含文本' Error的文件:

find . -ipath '*/fetch/evs/*.ev' | xargs grep -L -e "' Error" > try0.txt

此命令返回692个文件。奇怪的是,它忽略了满足标准的文件的一部分,例如,如果我这样做:

find . -ipath '*/fetch/evs/grades*.ev' | xargs grep -L -e "' Error" > try1.txt

此命令返回72个完全不在try0.txt的文件。

我真的无法理解这个......有人可以帮忙吗?

Edit1:我只是意识到我省略了一个非常重要的信息,实际上是在命令后引发了一条消息:xargs: unmatched single quote; by default quotes are special to xargs unless you use the -0 option。命令确实停止在名称包含'的文件中。为了纠正这个问题,我尝试了:

find . -ipath '*/fetch/evs/*.ev' | xargs -0 grep -L -e "' Error" > try3.txt

返回xargs: argument line too long和0档。

我也尝试过:

find . -ipath '*/fetch/evs/*.ev' -print0 | xargs -0 grep -L -e "' Error" > try4.txt

根本不会停止......

有没有人有任何想法?

3 个答案:

答案 0 :(得分:2)

这不仅仅是一个答案,但它也很难成为评论。

这是一个Perl脚本,可以模拟您的情况:

#!/usr/bin/env perl
use strict;
use warnings;
use File::Path qw(make_path);

my $subdir = "./fetch/evs";

make_path($subdir);

for my $i (0..999)
{
    {
    my $file1 = sprintf("%s/spare-%.3d.ev", $subdir, $i);
    open my $fh, '>', $file1 or die;
    printf $fh "Nothing to look at here\n" if ($i % 2 == 0);
    printf $fh "There is an ' Error ' here\n" if ($i % 2 == 1);
    close $fh;
    }
    {
    my $file2 = sprintf("%s/grades-%.3d.ev", $subdir, $i);
    open my $fh, '>', $file2 or die;
    printf $fh "Nothing to look at here\n" if ($i % 2 == 0);
    printf $fh "There is an ' Error ' here\n" if ($i % 2 == 1);
    close $fh;
    }
}

它创建了1,000个文件,其名称为spare-000.evspare-999.ev,还有grades-000.evgrades-999.ev的子目录fetch/evs(如有必要,它会创建)。奇数文件包含字符串' Error;偶数编号的文件没有。

在Mac OS X 10.8.5上运行:

find . -ipath '*/fetch/evs/grades*.ev' | xargs grep -L -e "' Error"

列出所有偶数编号的文件(不包含标记字符串)和

find . -ipath '*/fetch/evs/grades*.ev' | xargs grep -l -e "' Error"

列出所有奇数编号的文件(包含标记字符串)。因此,在Mac OS X上,您的问题无法重现。脚本在您的计算机上运行正常吗? (创建一个新的子目录或至少移动现有的子目录。)

如果这些命令适用于您的计算机,那么您列出的这些文件还有其他内容。如果这些命令在您的计算机上不起作用,则说明您的计算机存在根本问题(您上次重启的时间是什么时候?)。

然后呢

答案 1 :(得分:2)

这部分问题;

which returns xargs: argument line too long and 0 file.

是find返回太多文件以适应最大命令行长度。可以使用-n选项为xargs;

进行寻址
find . [snip] | xargs -n 5 ...

将导致xargs重复执行...仅使用5个文件名而不是所有文件名。

答案 2 :(得分:1)

如果您使用xargs: argument line too long,则不会遇到-exec问题。

说:

find . -ipath '*/fetch/evs/*.ev' -exec sh -c "grep -L -e \"' Error\" {}" \;

使用sh处理grep模式中的单引号。

编辑:没有sh

find . -ipath '*/fetch/evs/*.ev' -exec grep -L -e "' Error" {} \;