我想在文件夹中所有 csv 文件的所有行的末尾添加文件名(不带扩展名)。所有文件都具有相同的标头。
假设我的文件夹中有两个文件 a.csv 和 b.csv。
a.csv 包含(第一行是标题)
num1,num2,num3
1,2,3
b.csv 包含(第一行是标题)
num1,num2,num3
4,5,6
我想要一个 .csv 文件(第一行是标题)
num1,num2,num3,filename
1,2,3,a
我想要 b.csv 文件(第一行是标题)
num1,num2,num3,filename
4,5,6,b
我怎样才能在 Unix 中做到这一点?
答案1
for file in *.csv
do
filename=${file%.csv}
sed -i -e "1s/\$/,filename/; 2,\$s/\$/,$filename/" "$file"
done
- 循环遍历
*csv
当前目录中的每个文件, - 通过去掉尾随来准备文件名文本
.csv
-i
使用 sed 就地 编辑文件:- 仅在第 1 行上,搜索并用文本替换行尾(转义
$
),filename
。 - 在第 2 行到文件末尾 (
$
) 上,搜索行末尾 ($
) 并将其替换为逗号和准备好的文件名
- 仅在第 1 行上,搜索并用文本替换行尾(转义
答案2
如果我正确理解了OP,那么“理想”的解决方案是(第1行不带扩展名,其余带有扩展名),使用GNU awk
:
gawk -F, -i inplace \
'BEGIN {
OFS=",";
}
{
if(FNR==1)
name = gensub(/^(.*)\..*/, "\\1", "g", FILENAME);
else
name = FILENAME;
print $0, name;
}' *.csv
,句柄-F
和赋值OFS=","
将输入和输出字段分隔符设置为,
。
-i inplace
意味着截断文件中的当前记录并将当前输出写入文件中。
gensub 内置保存不带扩展名的文件名,并且 print 语句打印所需的修改记录。
答案3
以下命令使用磨坊主( mlr
) 读取 CSV 文件,并向每个文件添加一个名为 的新字段filename
,其中包含当前文件的路径名(在命令行上给出)并.csv
从末尾删除。
mlr -I --csv put '$filename = sub(FILENAME,"\.csv$","")' a.csv b.csv
使用-I
,可以就地对文件进行更改,并且每个文件都被单独处理。其余的内容应该熟悉awk
,还有一个好处是我们可以按名称引用字段。分配给新字段名称会创建该字段。
Miller 将自动引用任何需要引用的字段。
$ cat a.csv
num1,num2,num3
1,2,3
$ cat b.csv
num1,num2,num3
4,5,6
$ mlr -I --csv put '$filename = sub(FILENAME,"\.csv$","")' a.csv b.csv
$ cat a.csv
num1,num2,num3,filename
1,2,3,a
$ cat b.csv
num1,num2,num3,filename
4,5,6,b