将 header 添加到文件夹中的所有 .csv 文件并包含文件名

Adding header to all .csv files in folder and include filename

我是命令行新手,我正在尝试弄清楚如何将 header 添加到多个 .csv 文件。新的 header 应具有以下内容:'TaxID' 和 'filename'

我已经尝试了多个命令,如 sed、ed、awk、echo,但如果它起作用,它只更改了它找到的第一个文件(我在命令中说 *.csv),我只能为 TaxID 管理它。

任何人都可以帮助我将文件名也放入 header 并为我的所有 csv 文件执行此操作吗?

(注意,我使用的是 Mac)

谢谢!

这是在 perl 中通过添加 TaxID,{filename} 的 header 来修改文件的方法,如果它认为它已经存在则忽略添加 header。

ls
a.csv   b.csv

cat a.csv
1,a.txt
2,b.txt

cat b.csv
3,c.txt
4,d.txt

ls *.csv | xargs -I{} -n 1 \
perl -p -i -e 'print "TaxID,{}\n" if !m#^TaxID# && !$h; $h = 1;' {}

cat a.csv
TaxID,a.csv
1,a.txt
2,b.txt

cat b.csv
TaxID,b.csv
3,c.txt
4,d.txt

您可能想要创建一些文件备份,或者 运行 在 运行 正式开始之前对一些示例副本进行备份。

解释:

列出目录中扩展名为 .csv 的所有文件

ls *.csv

"Pipe" ls 命令的输出到 xargs 所以 perl 命令可以 运行 每个文件。 -I{} 允许随后使用 {} 引用文件名。 -n 告诉 xargs 一次只传递 1 个文件给 perl。

| xargs -I{} -n 1

-p 打印输入(文件)的每一行

-i 就地修改文件

-e执行以下代码

perl -p -i -e

Perl 将隐式循环遍历文件的每一行并打印它(由于 -p)。打印 header 如果我们还没有打印 header 并且当前行看起来不像 header.

'print "TaxID,{}\n" if !m#^TaxID# && !$h; $h = 1;'

这将替换为文件名。

{}

总而言之,在此示例中,运行 的命令将是:

perl -p -i -e 'print "TaxID,{}\n" if !m#^TaxID# && !$h; $h = 1;' a.csv
perl -p -i -e 'print "TaxID,{}\n" if !m#^TaxID# && !$h; $h = 1;' b.csv
perl -p -i -e 'print "TaxID,{}\n" if !m#^TaxID# && !$h; $h = 1;' c.csv
perl -p -i -e 'print "TaxID,{}\n" if !m#^TaxID# && !$h; $h = 1;' d.csv

这是一种方法,当然还有其他方法:

$ for i in *.csv;do echo $i;cp "$i" "$i.bak" && { echo "TaxID,$i"; cat "$i.bak"; } >"$i";done

这是一个示例 运行:

$ cat file1.csv
1,2
3,4
$ cat file2.csv
a,b
c,d
$ for i in *.csv;do echo $i;cp "$i" "$i.bak" && { echo "TaxID,$i"; cat "$i.bak"; } >"$i";done
file1.csv
file2.csv
$ cat file1.csv.bak
1,2
3,4
$ cat file1.csv
TaxID,file1.csv
1,2
3,4
$ cat file2.csv.bak
a,b
c,d
$ cat file2.csv
TaxID,file2.csv
a,b
c,d

分解:

$ for i in *.csv; do

循环遍历当前目录下所有以.csv结尾的文件。每个都会依次放入shell变量i中。

echo $i;

这只是呼应当前文件名,因此您可以看到进度。可以安全地忽略它。

cp "$i" "$i.bak"

将当前文件(其名称在 i 中)复制到备份。这既可以在出现问题时保留文件,也可以为后续命令提供可复制的内容。

&&

如果 cp 成功,则仅 运行 后续命令。如果无法备份,请不要继续。

{

开始群组命令。

echo "TaxID,$i";

输出想要的header.

cat "$i.bak";

输出原文件。

}

结束群组命令。

>"$i";

重定向组命令的输出(新的header和原文件的内容)到原文件。这样就完成了一个文件。

done

完成所有文件的循环。

为了好玩,这里有一些其他方法(一个 JRD 比我先用了),包括一个使用 ed!

$ for i in *.csv;do echo $i;perl -p -i.bak -e 'print "TaxID,$ARGV\n" if $. == 1' "$i";done
$ for i in *.csv;do echo $i;echo -e "1i\nTaxID,$i\n.\nw\nq\n" | ed "$i";done