处理大约 8000 个文件时“find: fts_read: Invalid argument”

处理大约 8000 个文件时“find: fts_read: Invalid argument”

GNU bash,版本3.2.48有这个bug; 3.2.57 版本已经没有了。

创建一个包含 8000 行相同行的文件(假设每行都写着1)。split -a3 -p "1"在其上运行(-p是一个 BSDsplit选项,它使其按照给定的模式进行分割。对于每行只有一个的文件,您可以通过运行1对标准执行相同的操作)。并执行splitsplit -a3 -b 1

find . -name xaaa -exec echo {} +

在预期输出之后,您将find: fts_read: Invalid argument输出到cerr.当被任何一组文件以及我尝试过的任何其他命令xaaa替换时,都会发生相同的错误。echo文件名的长度并不重要。文件的目录也并不重要。

在其他地方创建一些文件后,错误消失了。但是,当xaaa替换为xaa*(或任何其他包含多个文件的通配符,其中至少一个文件位于目录列表的开头附近)时,错误会再次发生。此时,没有任何单个文件会导致出现错误。

替换+;确实避免了错误,但对于我的脚本来说是不可接受的。这个问题在我的脚本中的其他情况下间歇性地发生,但通过减少它,我能够想出一种简单的方法来复制它。

我希望脚本在发生错误时停止,但这只会使其经常停止。知道如何解决这个问题吗? (例如,检索错误代码并忽略此特定错误)。

Mac 操作系统版本 10.8.5。 Darwin 内核版本 12.5.0。

答案1

bash 参与其中的可能性很小。

bash 的作用是解析该代码并将其转换为with , , , , , , ,find . -name xaaa -exec echo {} +的执行。任何 bash 版本都会做同样的事情。/path/to/findfind.-namexaaa-exececho{}+

这里,作为find:错误消息中的前缀,错误是 by find、 not bash,具体是关于函数返回的错误fts_read()

macosfind是 FreeBSD 的版本,可能经过 Apple 的修改。

值得庆幸的是,FreeBSD(如果不是 Macos)是 FLOSS,并且相对容易发现该错误在代码中输出

/*
 * find_execute --
 *  take a search plan and an array of search paths and executes the plan
 *  over all FTSENT's returned for the given search paths.
 */
int
find_execute(PLAN *plan, char *paths[])
[...]
    e = errno;
    finish_execplus();
    if (e && (!ignore_readdir_race || e != ENOENT))
        errc(1, e, "fts_read");
    return (exitstatus);
}

在该函数的最后find_execute

在这里我们得到:

 find: fts_read: Invalid argument

Invalid argument是与 errno 对应的错误消息EINVAL

这里将在调用之前在循环的条件语句中errno设置为fts_readas设置为 0 ,并且由于我们退出了循环,这意味着仅返回了。errnowhilefts_readfts_readNULL

如果你看一下的手册页fts_read, 你会找到:

函数fts_read()fts_children()可能会失败并设置为库函数、 、和指定的errno 任何错误。chdir(2)malloc(3)opendir(3)readdir(3)stat(2)

如果您按照这些链接访问其他手册页,则它们都不会返回 EINVAL。

所以它看起来很像苹果findfts那里的库中的一个错误。我建议您向 Apple 支持人员提出这个问题,因为如果无法访问代码,我们可能就无能为力了。

相关内容