我有多个csv文件,每个文件需要放置在第1行的标题数据,来自一个长度为1行的单独csv文件。该文件名为Anon_student_ID,目录中的每个其他文件都需要此数据作为第1行,同时保留其文件名。
我正在尝试从命令行使用cat函数。
我尝试解决的问题是 - $ cat Anon_student_ID.csv *.csv > *.csv
但是,我得到bash: *.csv: ambiguous redirect
,
有人可以解释为什么它不采用第二个文件名并将其用作输出文件名吗?什么是更好的方法。
由于
答案 0 :(得分:2)
#!/bin/bash
shopt -s nullglob
shopt -s extglob
TEMP=$(mktemp)
IFS= read -r HEADER < Anon_student_ID.csv
for CSV in !(Anon_student_ID).csv; do
{ echo "$HEADER"; cat "$CSV"; } > "$TEMP" && cat "$TEMP" > "$CSV"
done
rm -f "$TEMP"
nullglob
可防止模式在未找到匹配项时显示。extglob
启用了!(...)
等扩展模式。!(Anon_student_ID).csv
匹配所有不具有文件名Anon_student_ID
的CSV文件。sed
很好,但在这方面看起来会很糟糕。这也需要重复读取头文件。如果文件不是那么大,那么使用数组作为缓冲区而不是临时文件也是好的:
#!/bin/bash
shopt -s nullglob
shopt -s extglob
[[ BASH_VERSINFO -ge 4 ]] || exit 1 ## Make sure we have `readarray`
IFS= read -r HEADER < Anon_student_ID.csv
for CSV in !(Anon_student_ID).csv; do
readarray -t LINES < "$CSV"
printf '%s\n' "$HEADER" "${LINES[@]}" > "$CSV"
done
答案 1 :(得分:1)
作为一个单行:
mv Anon_student_ID.csv Anon_student_ID; for i in *.csv; do cat Anon_student_ID > tmpfile; cat ${i} >> tmpfile; mv tmpfile ${i}; done; mv Anon_student_ID Anon_student_ID.csv
以可读格式:
#!/bin/bash
mv Anon_student_ID.csv Anon_student_ID
for i in *.csv; do
cat Anon_student_ID > tmpfile
cat ${i} >> tmpfile
mv tmpfile ${i}
done
mv Anon_student_ID Anon_student_ID.csv
Anon_student_ID已重命名,因此它不会用于将自身附加到自身,因为它也会匹配*.csv
。