Bash解析多个CSV文件时如何获取当前读取的文件名
Shell批量合并CSV并附带文件名的实现方案
你之前用cat $files | while read的写法从根源上无法获取行所属文件名——所有文件内容被提前拼接成了一个无边界的文本流,文件之间的分隔信息已经丢失了。之前嵌套for循环报错基本是没做特殊字符兼容、没有正确给while循环指定输入源导致的,按下面的写法实现即可:
可直接运行的代码
#!/bin/bash # 定义合并后的输出文件 OUTPUT="merged_result.csv" # 写入合并后的表头,可根据自己的列名调整 echo "source_file,col1,col2" > "$OUTPUT" # 遍历目标目录下所有CSV文件 for csv_file in /CSVFiles/*.csv; do # 无匹配CSV时跳过,避免把通配符字符串当成文件名处理 [ -f "$csv_file" ] || continue # 提取不带路径、不带.csv后缀的文件名(例如/CSVFiles/foo.csv → foo) file_name=${csv_file##*/} file_name=${file_name%.csv} # 逐行读取当前CSV内容 while IFS=',' read -r col1 col2 || [ -n "$col1" ]; do # 拼接文件名和列内容写入输出文件 echo "$file_name,$col1,$col2" >> "$OUTPUT" done < "$csv_file" done
关键逻辑说明
- 文件名提取用Shell原生字符串截取实现,不需要额外调用外部命令:
${csv_file##*/}:删除最后一个/前的所有路径内容,得到带后缀的文件名${file_name%.csv}:删除字符串末尾的.csv后缀,得到纯文件名
- 所有变量加双引号包裹,兼容带空格、特殊字符的文件名和CSV内容,不会出现解析异常
- 读行时加
|| [ -n "$col1" ]是为了兼容CSV最后一行没有换行符的边界情况,避免遗漏最后一行数据 - 如果需要保留完整文件路径,直接用
$csv_file作为文件名字段即可;如果需要保留.csv后缀,跳过后缀截取的步骤就行
注意:如果你的CSV本身带表头,且不希望每个文件的表头都被写入合并文件,可以在while循环里加一个行号判断,跳过每个文件的第一行即可。
内容的提问来源于stack exchange,提问作者madeleine
相关产品推荐
相关产品推荐

