3

似乎我无法找到这个问题的直接答案。我感谢您的帮助。我正在尝试在目录中查找具有特定名称的所有文件,读取文件的最后 1000 行并将其复制到同一目录中的新文件中。举个例子:

在当前目录中找到所有名为 xyz.log 的文件,将最后 1000 行复制到文件 abc.log(不存在)。

我尝试使用以下命令,但没有成功:

寻找 。-name "xyz.log" -execdir tail -1000 {} > abc.log \;

我遇到的问题是,对于当前目录中的所有文件,它们都写入 CURRENT 目录中的 abc.log 而不是 xyz.log 所在的目录。很明显,首先执行带有 execdir 的查找,然后将输出重定向到 abc.log。

你们能提出解决这个问题的方法吗?我感谢任何信息/帮助。

编辑-我试过 find 。-name "xyz.log" -execdir sh -c "tail -1000 {} > abc.log" \; 正如一些朋友所建议的,但它给了我这个错误:“sh:./tail:没有这样的文件或目录”错误消息。你们知道问题是什么吗?

幸运的是,使用 -printf 的解决方案运行良好。

4

3 回答 3

5

最简单的方法是这样的:

find . -name "xyz.log" -execdir sh -c 'tail -1000 "{}" >abc.log' \;

一种更灵活的替代方法是首先打印出命令,然后使用以下命令全部执行sh

find . -name "xyz.log" -printf 'tail -1000 "%p" >"%h/abc.log"\n' | sh

您可以| sh在尝试/调试时从最后删除。

在 findutils 的某些版本(4.2 和 4.3,尽管它在某些 4.2.x 和 4.3.x 版本中已修复)中存在一个错误,导致包含{}前缀的execdir 参数./(而不是仅应用于{}它的前缀是应用于整个引用的字符串)。要解决此问题,您可以使用:

find . -name "xyz.log" -execdir sh -c 'tail -1000 "$1" >abc.log' sh {} \;

sh -c 'script' arg0 arg1sh script使用传递给它的 arg0、arg1 等运行。按照惯例,arg0 是可执行文件的名称(此处为“sh”)。从脚本中,您可以使用$0(对应于“sh”)、$1(对应于 find 的扩展{})等访问参数。

于 2013-06-21T20:53:31.070 回答
0

重定向不会传递到 execdir,因此 abc.log 会显示在您运行命令的目录中。-execdir 也不喜欢嵌入式重定向。但是您可以通过向 -execdir 传递嵌入了重定向的 shell 命令来解决此问题,如下所示:

find . -name "xyz.log" -execdir sh -c '/usr/bin/tail -1000 {} > abc.log' \;

这篇博文的很多功劳(不是我的):

http://www.microhowto.info/howto/act_on_all_files_in_a_directory_tree_using_find.html

编辑

我将 tail 的完整路径放在命令中(假设它在您系统上的 /usr/bin 中),因为 sh 可能会加载一个 .profile ,其 PATH 与您当前的 shell 不同。

于 2013-06-21T20:59:14.700 回答
0

这是另一个非find(嗯,排序 - 它仍然使用find但不试图硬塞find到做整个事情):

while read f
do
  d=$(dirname "${f}")
  tail -n 1000 "${f}" > "${d}/abc.log"
done < <(find . -type f -name xyz.log -print)
于 2013-07-02T16:38:17.917 回答