将循环每次迭代的输出附加到 bash 中的相同内容
append output of each iteration of a loop to the same in bash
我有 44 个文件(每个染色体 2 个)分为两种类型:.vcf 和 .filtered.vcf。
我想在一个循环中为它们中的每一个制作一个 wc -l
并将输出始终附加到同一个文件。但是,我想在此文件中包含 3 列:chr[1-22]、.vcf 的 wc -l
和 .filtered.vcf 的 wc -l
。
我一直在尝试为每个文件做独立的 wc -l
并将每个染色体的 2 个输出按列粘贴在一起,但这显然不是很有效,因为我生成了很多不必要的文件。我正在为 22 对文件尝试此代码:
wc -l file1.vcf | cut -f 1 > out1.vcf
wc -l file1.filtered.vcf | cut -f 1 > out1.filtered.vcf
paste -d "\t" out1.vcf out1.filtered.vcf
我想要一个包含三列的输出文件:
Chromosome VCFCount FilteredVCFCount
chr1 out1 out1.filtered
chr2 out2 out2.filtered
任何帮助将不胜感激,非常感谢您:)
printf "%s\n" *.filtered.vcf |
cut -d. -f1 |
sort |
xargs -n1 sh -c 'printf "%s\t%s\t%s\n" "" "$(wc -l <".vcf")" "$(wc -l <".filtered.vcf")"' --
- 输出目录中文件的换行符分隔列表
- 用 cut 删除扩展(可能
xargs -i basename {} .filtered.vcf
上的东西会更安全)
- 对其进行排序(以获得漂亮的排序输出!)(可能
sort -tr -k2 -n
中的某些内容会按数字排序并且会更好)。
xargs -n1
对每个文件执行脚本 sh -c
printf "%s\t%s\t%s\n"
- 使用自定义格式字符串输出 ...
""
- 文件名和...
"(wc -l <".vcf")"
- 计算 .vcf 文件中的行数和...
"$(wc -l <".filtered.vcf")"
- .filtered.vcf 中的行数
示例:
> touch chr{1..3}{,.filtered}.vcf
> echo > chr1.filtered.vcf ; echo > chr2.vcf ;
> printf "%s\n" *.filtered.vcf |
> cut -d. -f1 |
> sort |
> xargs -n1 sh -c 'printf "%s\t%s\t%s\n" "" "$(wc -l <".filtered.vcf")" "$(wc -l <".vcf")"' --
chr1 0 1
chr2 1 0
chr3 0 0
要使 table 与 headers 相得益彰,请使用 column
:
> .... | column -N Chromosome,VCFCount,FilteredVCFCount -t -o ' '
Chromosome VCFCount FilteredVCFCount
chr1 0 1
chr2 1 0
chr3 0 0
也许试试这个。
for chr in chr*.vcf; do
base=${chr%.vcf}
awk -v base="$base" 'BEGIN { OFS="\t"
# Remove this to not have this pesky header line
print "Chromosome", "VCFCount", "FilteredVCFCount"
}
FNR==1 && n { p=n }
{ n=FNR }
END { print base, p, n }' "$chr" "$base.filtered.vcf"
done >counts.txt
非常简单的 Awk 脚本只是收集每个文件的最高行号(因此我们基本上重新实现 wc -l
)并以所需格式打印收集到的数字。 FNR
是当前输入文件中的行号;我们只需保存它,并将值复制到 p
,以便在我们切换到新文件时(从第 1 行重新开始)将先前文件中保存的值保存在单独的变量中。
shell 参数替换 ${variable%pattern}
检索 variable
的值,删除了 pattern
上的任何后缀匹配。 (还有${variable#pattern}
去掉一个前缀,Bash有##
和%%
到trim最长的模式匹配,而不是最短的。)
如果效率很重要,您可以将所有脚本重构为一个 Awk 脚本,但这样一来,所有部分都很简单,而且希望易于理解。
我有 44 个文件(每个染色体 2 个)分为两种类型:.vcf 和 .filtered.vcf。
我想在一个循环中为它们中的每一个制作一个 wc -l
并将输出始终附加到同一个文件。但是,我想在此文件中包含 3 列:chr[1-22]、.vcf 的 wc -l
和 .filtered.vcf 的 wc -l
。
我一直在尝试为每个文件做独立的 wc -l
并将每个染色体的 2 个输出按列粘贴在一起,但这显然不是很有效,因为我生成了很多不必要的文件。我正在为 22 对文件尝试此代码:
wc -l file1.vcf | cut -f 1 > out1.vcf
wc -l file1.filtered.vcf | cut -f 1 > out1.filtered.vcf
paste -d "\t" out1.vcf out1.filtered.vcf
我想要一个包含三列的输出文件:
Chromosome VCFCount FilteredVCFCount
chr1 out1 out1.filtered
chr2 out2 out2.filtered
任何帮助将不胜感激,非常感谢您:)
printf "%s\n" *.filtered.vcf |
cut -d. -f1 |
sort |
xargs -n1 sh -c 'printf "%s\t%s\t%s\n" "" "$(wc -l <".vcf")" "$(wc -l <".filtered.vcf")"' --
- 输出目录中文件的换行符分隔列表
- 用 cut 删除扩展(可能
xargs -i basename {} .filtered.vcf
上的东西会更安全) - 对其进行排序(以获得漂亮的排序输出!)(可能
sort -tr -k2 -n
中的某些内容会按数字排序并且会更好)。 xargs -n1
对每个文件执行脚本sh -c
printf "%s\t%s\t%s\n"
- 使用自定义格式字符串输出 ...""
- 文件名和..."(wc -l <".vcf")"
- 计算 .vcf 文件中的行数和..."$(wc -l <".filtered.vcf")"
- .filtered.vcf 中的行数
示例:
> touch chr{1..3}{,.filtered}.vcf
> echo > chr1.filtered.vcf ; echo > chr2.vcf ;
> printf "%s\n" *.filtered.vcf |
> cut -d. -f1 |
> sort |
> xargs -n1 sh -c 'printf "%s\t%s\t%s\n" "" "$(wc -l <".filtered.vcf")" "$(wc -l <".vcf")"' --
chr1 0 1
chr2 1 0
chr3 0 0
要使 table 与 headers 相得益彰,请使用 column
:
> .... | column -N Chromosome,VCFCount,FilteredVCFCount -t -o ' '
Chromosome VCFCount FilteredVCFCount
chr1 0 1
chr2 1 0
chr3 0 0
也许试试这个。
for chr in chr*.vcf; do
base=${chr%.vcf}
awk -v base="$base" 'BEGIN { OFS="\t"
# Remove this to not have this pesky header line
print "Chromosome", "VCFCount", "FilteredVCFCount"
}
FNR==1 && n { p=n }
{ n=FNR }
END { print base, p, n }' "$chr" "$base.filtered.vcf"
done >counts.txt
非常简单的 Awk 脚本只是收集每个文件的最高行号(因此我们基本上重新实现 wc -l
)并以所需格式打印收集到的数字。 FNR
是当前输入文件中的行号;我们只需保存它,并将值复制到 p
,以便在我们切换到新文件时(从第 1 行重新开始)将先前文件中保存的值保存在单独的变量中。
shell 参数替换 ${variable%pattern}
检索 variable
的值,删除了 pattern
上的任何后缀匹配。 (还有${variable#pattern}
去掉一个前缀,Bash有##
和%%
到trim最长的模式匹配,而不是最短的。)
如果效率很重要,您可以将所有脚本重构为一个 Awk 脚本,但这样一来,所有部分都很简单,而且希望易于理解。