Bash-遍历输出线

时间:2018-12-26 17:22:03

标签: bash

我想要什么:找到所有nginx访问日志文件,对其进行迭代(从中获取一些数据)。

我被困在for循环中:

#!/bin/bash

logfiles="$(find /var/log/nginx -name 'access.log*')"

for lf in "$logfiles"
do
    echo "file"
done

尽管有多个日志文件,但输出仅是一个“文件”字。怎么了?

2 个答案:

答案 0 :(得分:4)

当你说

for lf in "$logfiles"

您的引号会保留find输出中的空格。在这种情况下,引号是不正确的。删除它们将正确遍历文件:

$ for i in "`find . -iname '*.log'`"; do echo $i; done
./2.log ./3.log ./1.log

$ for i in `find . -iname '*.log'`; do echo $i; done
./2.log
./3.log
./1.log

但是有更好的方法:您应该数据,而不是进行迭代。考虑这种模式:

$ find . -iname '*.log' | xargs -n 1 echo
./2.log
./3.log
./1.log

非常值得将您的头放在xargs周围,这会将其标准输入转换为附加参数,以添加到自己的参数中,然后执行该参数。在这种简单情况下,我告诉xargs为文件的每1(echo)分别运行命令-n 1

有几个原因xargs是我尽可能使用的迭代运算符:首先,它非常聪明。使用for i in $(command)遍历命令输出需要$(command)item1 item2 item3的形式提供您的列表,如果任何项目包含特殊字符,则这些问题会引起问题,然后bash 将其解释为for参数的一部分

以下是该空间的一个示例,该空间通常在bash中作为有效的输入字段spearator变得特别。

$ for i in `find . -iname '*.log'`; do echo $i; done
./4
tricky.log
./2.log
./3.log
./1.log

包含空格的文件4 tricky.log现在引起了问题。

xargs足够聪明,可以将它们分开。在某些情况下,可以通过更改$IFS(输入字段分隔符)来解决此问题。但这变得很快。使用xargs,您有更好的选择-具体来说,xargs也可以使用空字符以-0字符终止其输入流中的项目。其他程序find也可以在输出中使用空字符来匹配xargs的期望值。从这个意义上讲,xargsfind是很好的组合:

$ find . -iname '*.log' -print0 | xargs -0 -n 1 echo
./4 tricky.log
./2.log
./3.log
./1.log

但是,等等,还有更多!命令的下一步肯定是对grep文件进行查找,以查找要查找的任何匹配行。如果行很大,那么您也将要并行化。 xargs也可以这样做。您可以在管道中添加更多步骤进行过滤等。

最后,使用子shell替换$()作为程序参数可能会导致意外命令,如果在使用它们时要非常小心,以避免在失败情况下产生意外参数。我曾经写过一个脚本,该脚本使用$()查找mysql的源目录以进行一些首次安装。它说了类似remove -r /$(find / -iname mysqldir)的内容。好吧,如果预期位置中没有mysqldir变成rm -r /。显然不是我想要的:天哪!

这就是为什么我尽可能使用并鼓励其他人使用xargs的原因。

答案 1 :(得分:2)

删除此行中的引号:HAVING 但是看来您可能只有一个名为access.log的文件