我所在的目录有几千个文件,但我想要过滤的文件都具有以下语法:*.imputed.*_info
我想使用 awk 过滤掉每个文件中第五列数据的值 > 0.50 的记录,我可以使用以下方法来做到这一点:awk '{if($5 >= .5) {print}}' filename
。
那也有效。然后,我尝试循环遍历所有 500 个左右的文件,并将每个文件中符合此条件的记录连接起来。
我尝试了以下方法,但语法不正确。
touch snplist.txt
for name in *.imputed.*_info; do
snps="awk '{if($5 >= .5) {print}}' $name"
cat snplist.txt "$snps" > snplist.txt
done
答案1
您的代码在每次迭代中都会覆盖输出文件。你实际上也没有打电话awk
。
你想做的是这样的
awk '$5 >= 0.5' ./*.imputed.*_info >snplist.txt
这将awk
立即调用所有文件,并按照 shell 扩展通配模式的顺序逐一遍历它们。如果文件中任何行的第 5 列大于或等于 0.5,则该行将被输出(到snplist.txt
)。这是有效的,因为如果没有操作({...}
块)与条件关联,则默认操作是输出当前行。
如果您有大的文件数量(数千),这可能会生成“参数列表太长”错误。在这种情况下,您可能需要循环:
for filename in ./*.imputed.*_info; do
awk '$5 >= 0.5' "$filename"
done >snplist.txt
请注意, 的结果awk
不需要存储在变量中。在这里,它只是输出循环(因此循环内的所有命令)被重定向到snplist.txt
.
对于数千个文件,这将非常慢,因为awk
需要单独调用每个文件。
为了加快速度,如果单次调用有太多文件awk
,您可以考虑使用xargs
如下所示:
printf '%s\0' ./*.imputed.*_info | xargs -0 awk '$5 >= 0.5' >snplist.txt
这将创建一个文件名列表,并将它们作为一个以 null 结尾的列表printf
传递。xargs
该xargs
实用程序将采用这些并awk
开始尽可能多的一次,分批。整个管道的输出将被重定向到snplist.txt
.
这种xargs
替代方案假设您使用的是 Unix,例如 Linux,它有一个xargs
命令可以实现非标准-0
选项来读取以 nul 结尾的输入。它还假设您使用的是 shell,例如bash
,它具有内置 printf
实用程序(ksh
,OpenBSD 上的默认 shell,在这里不起作用,因为它没有这样的内置实用程序)。
对于zsh
外壳(即不是bash
):
autoload -U zargs
zargs -- ./*.imputed.*_info -- awk '$5 >= 0.5' >snplist.txt
它使用,它基本上是作为可加载shell 函数zargs
的重新实现。有关详细信息,请参阅(加载函数后)和手册。xargs
zsh
zargs --help
zshcontrib(1)
答案2
只需这样做:
awk '$5 >= .5' *.imputed.*_info > snplist.txt
答案3
find
我有使用这种东西的习惯。
find . -type f -name "*.imputed.*_info" -exec awk '$5 >= 0.5' {} \; > ./snplist.txt