GNU bash,版本3.2.48有这个bug; 3.2.57 版本已经没有了。
创建一个包含 8000 行相同行的文件(假设每行都写着1
)。split -a3 -p "1"
在其上运行(-p
是一个 BSDsplit
选项,它使其按照给定的模式进行分割。对于每行只有一个的文件,您可以通过运行1
对标准执行相同的操作)。并执行split
split -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/find
find
.
-name
xaaa
-exec
echo
{}
+
这里,作为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_read
as设置为 0 ,并且由于我们退出了循环,这意味着仅返回了。errno
while
fts_read
fts_read
NULL
如果你看一下的手册页fts_read
, 你会找到:
函数
fts_read()
和fts_children()
可能会失败并设置为库函数、 、和指定的errno
任何错误。chdir(2)
malloc(3)
opendir(3)
readdir(3)
stat(2)
如果您按照这些链接访问其他手册页,则它们都不会返回 EINVAL。
所以它看起来很像苹果find
或fts
那里的库中的一个错误。我建议您向 Apple 支持人员提出这个问题,因为如果无法访问代码,我们可能就无能为力了。