我有一个模板 A.tsv (字段分隔符=\t):
Name data
还有几个文件,例如B.txt和C.txt。
我想打印文件名中的文件名(但在新文件中),如下所示:
Name data
B
C
我已经这样做了:
template="A.tsv"
for bla in data/*.txt ; do
r="$(basename -s ".txt" $bla)"
( head -n 1 $template
awk -F'\t' -v OFS="\t" -v filename=$r '{print filename}' $bla ) > test_name.tsv ;
done
但它给了我:
Name data
C
C
C
C
C
C
C
你知道我的命令有什么问题吗?
谢谢
答案1
带有详细注释的脚本:
#!/bin/bash
#using the template variable is redundant, but
#I assume you want to use that lateron
template="A.tsv"
#write header from template and create file "output.txt"
#overwrites old version of "output.txt" if existing
head -n 1 ${template} > output.txt
#loop over files:
for bla in data/*.txt ; do
#get basename without file suffix, add result to "output.txt"
basename -s ".txt" ${bla} >> output.txt
done
请注意,您应该更喜欢使用${variable}
或"$varaible"
,尤其是对于文件名,否则如果文件名称中包含例如空格,脚本将中断。
为什么awk
- 方法失败了?
awk
以每行为基础运行。你的代码有这样的:
awk -v variable=$r '{print variable}' ${file}
因此,当您有一个包含 10 行的文件时,上述命令将执行 10 次并产生 10 行变量。要awk
在一次运行后停止,请使用exit
或指定应执行命令的行:
#execute command only on line no. 1
awk 'NR == 1 { print $1 }' file
#execute command and quit awk
awk '{ print 1 ; exit }'
原来的脚本还有哪里失败了?
>>
会将输出附加到文件中,并>
覆盖它。在您的脚本中,您有一个包含以下内容的循环:
( head -n 1 $template
awk [...] $bla ) > test_name.tsv
发生的情况是,对于 中的每场比赛data/*txt
,都会运行此命令,从而覆盖 的以前版本test_name.tsv
,只留下最后一次运行的版本。请注意您如何在每次循环运行中重写标头。